Merge mozilla-central and tracemonkey. (a=blockers)

This commit is contained in:
Chris Leary 2011-01-24 19:47:52 -08:00
commit f834b150eb
70 changed files with 1430 additions and 492 deletions

View File

@ -880,9 +880,9 @@ var gSyncSetup = {
// if no property string is passed in, we clear label/style
_setFeedback: function (element, success, string) {
element.hidden = success || !string;
let class = success ? "success" : "error";
let classname = success ? "success" : "error";
let image = element.getElementsByAttribute("class", "statusIcon")[0];
image.setAttribute("status", class);
image.setAttribute("status", classname);
let label = element.getElementsByAttribute("class", "status")[0];
label.value = string;
},

View File

@ -146,9 +146,9 @@ BrowserGlue.prototype = {
// delays are in seconds
const MAX_DELAY = 300;
let delay = 3;
let enum = Services.wm.getEnumerator("navigator:browser");
while (enum.hasMoreElements()) {
delay += enum.getNext().gBrowser.tabs.length;
let browserEnum = Services.wm.getEnumerator("navigator:browser");
while (browserEnum.hasMoreElements()) {
delay += browserEnum.getNext().gBrowser.tabs.length;
}
delay = delay <= MAX_DELAY ? delay : MAX_DELAY;

View File

@ -703,10 +703,10 @@ Application.prototype = {
get windows() {
var win = [];
var enum = Utilities.windowMediator.getEnumerator("navigator:browser");
var browserEnum = Utilities.windowMediator.getEnumerator("navigator:browser");
while (enum.hasMoreElements())
win.push(new Window(enum.getNext()));
while (browserEnum.hasMoreElements())
win.push(new Window(browserEnum.getNext()));
return win;
},

View File

@ -71,8 +71,6 @@
#include "nsINode.h"
#include "nsHashtable.h"
#include "jsapi.h"
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
class nsIDOMScriptObjectFactory;

View File

@ -21,8 +21,8 @@
<script type="application/javascript">
<![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function testStatics() {

View File

@ -15,8 +15,8 @@
<script type="application/javascript"><![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok", "snapshotWindow",
"compareSnapshots", "onerror" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function $(id) {

View File

@ -47,8 +47,8 @@
<script type="application/javascript"><![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok"];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
const text="MOZILLA";

View File

@ -9,8 +9,8 @@
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function $(id) {

View File

@ -9,8 +9,8 @@
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function $(id) {

View File

@ -3,8 +3,8 @@
*/
var imports = [ "SimpleTest", "is", "isnot", "ok", "onerror", "todo",
"todo_is", "todo_isnot" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
/**

View File

@ -1970,18 +1970,6 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
PRUint32 argc = 0;
jsval *argv = nsnull;
js::LazilyConstructed<nsAutoPoolRelease> poolRelease;
js::LazilyConstructed<js::AutoArrayRooter> tvr;
// Use |target| as the scope for wrapping the arguments, since aScope is
// the safe scope in many cases, which isn't very useful. Wrapping aTarget
// was OK because those typically have PreCreate methods that give them the
// right scope anyway, and we want to make sure that the arguments end up
// in the same scope as aTarget.
rv = ConvertSupportsTojsvals(aargv, target, &argc,
&argv, poolRelease, tvr);
NS_ENSURE_SUCCESS(rv, rv);
JSObject *funobj = static_cast<JSObject *>(aHandler);
nsCOMPtr<nsIPrincipal> principal;
rv = sSecurityManager->GetObjectPrincipal(mContext, funobj,
@ -2001,6 +1989,18 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
return NS_ERROR_FAILURE;
}
js::LazilyConstructed<nsAutoPoolRelease> poolRelease;
js::LazilyConstructed<js::AutoArrayRooter> tvr;
// Use |target| as the scope for wrapping the arguments, since aScope is
// the safe scope in many cases, which isn't very useful. Wrapping aTarget
// was OK because those typically have PreCreate methods that give them the
// right scope anyway, and we want to make sure that the arguments end up
// in the same scope as aTarget.
rv = ConvertSupportsTojsvals(aargv, target, &argc,
&argv, poolRelease, tvr);
NS_ENSURE_SUCCESS(rv, rv);
++mExecuteDepth;
PRBool ok = ::JS_CallFunctionValue(mContext, target,
funval, argc, argv, &rval);

View File

@ -160,8 +160,11 @@ nsresult CentralizedAdminPrefManagerInit()
static_cast<nsIXPCSecurityManager*>(new AutoConfigSecMan());
xpc->SetSecurityManagerForJSContext(autoconfig_cx, secman, 0);
autoconfig_glob = JS_NewGlobalObject(autoconfig_cx, &global_class);
autoconfig_glob = JS_NewCompartmentAndGlobalObject(autoconfig_cx, &global_class, NULL);
if (autoconfig_glob) {
JSAutoEnterCompartment ac;
if(!ac.enter(autoconfig_cx, autoconfig_glob))
return NS_ERROR_FAILURE;
if (JS_InitStandardClasses(autoconfig_cx, autoconfig_glob)) {
// XPCONNECT enable this JS context
rv = xpc->InitClasses(autoconfig_cx, autoconfig_glob);

View File

@ -0,0 +1,3 @@
var COUNT = RUNLOOP;
eval("'use strict'; for (let j = 0; j < COUNT; j++); try { x; throw new Error(); } catch (e) { if (!(e instanceof ReferenceError)) throw e; }");
assertEq(typeof j, "undefined");

View File

@ -0,0 +1,2 @@
for (var j=0; j<HOTLOOP; ++j)
({'0': 0});

View File

@ -0,0 +1,10 @@
// vim: set ts=4 sw=4 tw=99 et:
var count = 0;
watch("x", function() {
count++;
});
for(var i=0; i<10; i++) {
x = 2;
}
assertEq(count, 10);

View File

@ -3820,6 +3820,9 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
if (obj->isGlobal()) {
for (int key = JSProto_Null; key < JSProto_LIMIT * 3; key++)
JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
/* Clear the CSP eval-is-allowed cache. */
JS_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_EVAL_ALLOWED, JSVAL_VOID);
}
js_InitRandom(cx);

View File

@ -1939,10 +1939,12 @@ struct JSClass {
#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
/* Additional global reserved slots, beyond those for standard prototypes. */
#define JSRESERVED_GLOBAL_SLOTS_COUNT 3
#define JSRESERVED_GLOBAL_SLOTS_COUNT 5
#define JSRESERVED_GLOBAL_THIS (JSProto_LIMIT * 3)
#define JSRESERVED_GLOBAL_THROWTYPEERROR (JSRESERVED_GLOBAL_THIS + 1)
#define JSRESERVED_GLOBAL_REGEXP_STATICS (JSRESERVED_GLOBAL_THROWTYPEERROR + 1)
#define JSRESERVED_GLOBAL_FUNCTION_NS (JSRESERVED_GLOBAL_REGEXP_STATICS + 1)
#define JSRESERVED_GLOBAL_EVAL_ALLOWED (JSRESERVED_GLOBAL_FUNCTION_NS + 1)
/*
* ECMA-262 requires that most constructors used internally create objects

View File

@ -1221,8 +1221,7 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
* Use HashTable entry as the cycle indicator. On first visit, create the
* entry, and, when leaving, remove the entry.
*/
typedef js::HashSet<JSObject *> ObjSet;
ObjSet::AddPtr hashp = cx->busyArrays.lookupForAdd(obj);
BusyArraysMap::AddPtr hashp = cx->busyArrays.lookupForAdd(obj);
uint32 genBefore;
if (!hashp) {
/* Not in hash table, so not a cycle. */

View File

@ -746,6 +746,11 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_ASSERT(cx->resolveFlags == 0);
if (!cx->busyArrays.init()) {
FreeContext(cx);
return NULL;
}
#ifdef JS_THREADSAFE
if (!js_InitContextThread(cx)) {
FreeContext(cx);
@ -841,12 +846,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
return NULL;
}
/* Using ContextAllocPolicy, so init after JSContext is ready. */
if (!cx->busyArrays.init()) {
FreeContext(cx);
return NULL;
}
return cx;
}
@ -1994,7 +1993,7 @@ JSContext::JSContext(JSRuntime *rt)
: runtime(rt),
compartment(NULL),
regs(NULL),
busyArrays(thisInInitializer())
busyArrays()
{}
void

View File

@ -833,7 +833,7 @@ private:
_(joinedsetmethod), _(joinedinitmethod), \
_(joinedreplace), _(joinedsort), _(joinedmodulepat), \
_(mreadbarrier), _(mwritebarrier), _(mwslotbarrier), \
_(unjoined)
_(unjoined), _(indynamicscope)
# define identity(x) x
struct JSFunctionMeter {
@ -1633,6 +1633,10 @@ VersionIsKnown(JSVersion version)
return VersionNumber(version) != JSVERSION_UNKNOWN;
}
typedef js::HashSet<JSObject *,
js::DefaultHasher<JSObject *>,
js::SystemAllocPolicy> BusyArraysMap;
} /* namespace js */
struct JSContext
@ -1732,7 +1736,7 @@ struct JSContext
/* State for object and array toSource conversion. */
JSSharpObjectMap sharpObjectMap;
js::HashSet<JSObject *> busyArrays;
js::BusyArraysMap busyArrays;
/* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
JSArgumentFormatMap *argumentFormatMap;
@ -2133,9 +2137,6 @@ struct JSContext
* a boolean flag to minimize the amount of code in its inlined callers.
*/
JS_FRIEND_API(void) checkMallocGCPressure(void *p);
/* To silence MSVC warning about using 'this' in a member initializer. */
JSContext *thisInInitializer() { return this; }
}; /* struct JSContext */
#ifdef JS_THREADSAFE

View File

@ -64,8 +64,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
marked(false),
active(false),
debugMode(rt->debugMode),
anynameObject(NULL),
functionNamespaceObject(NULL),
mathCache(NULL)
{
JS_INIT_CLIST(&scripts);

View File

@ -374,16 +374,6 @@ struct JS_FRIEND_API(JSCompartment) {
bool debugMode; // true iff debug mode on
JSCList scripts; // scripts in this compartment
/*
* Weak references to lazily-created, well-known XML singletons.
*
* NB: Singleton objects must be carefully disconnected from the rest of
* the object graph usually associated with a JSContext's global object,
* including the set of standard class objects. See jsxml.c for details.
*/
JSObject *anynameObject;
JSObject *functionNamespaceObject;
JSC::ExecutableAllocator *regExpAllocator;
js::NativeIterCache nativeIterCache;

View File

@ -7090,12 +7090,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_FALSE;
break;
#if JS_HAS_DEBUGGER_KEYWORD
case TOK_DEBUGGER:
if (js_Emit1(cx, cg, JSOP_DEBUGGER) < 0)
return JS_FALSE;
break;
#endif /* JS_HAS_DEBUGGER_KEYWORD */
#if JS_HAS_XML_SUPPORT
case TOK_XMLELEM:

View File

@ -262,6 +262,11 @@ struct JSStmtInfo {
*/
#define TCF_HAS_SINGLETONS 0x8000000
/*
* Some enclosing scope is a with-statement or E4X filter-expression.
*/
#define TCF_IN_WITH 0x10000000
/*
* Flags to check for return; vs. return expr; in a function.
*/

View File

@ -2424,7 +2424,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
* Report errors via CSP is done in the script security manager.
* js_CheckContentSecurityPolicy is defined in jsobj.cpp
*/
if (!js_CheckContentSecurityPolicy(cx)) {
if (!js_CheckContentSecurityPolicy(cx, parent)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
return JS_FALSE;
}

View File

@ -5398,7 +5398,7 @@ BEGIN_CASE(JSOP_DEFFUN)
*/
obj2 = &regs.fp->scopeChain();
} else {
JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
JS_ASSERT(!fun->isFlatClosure());
obj2 = GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
if (!obj2)
@ -5436,62 +5436,54 @@ BEGIN_CASE(JSOP_DEFFUN)
*/
JSObject *parent = &regs.fp->varobj(cx);
/*
* Check for a const property of the same name -- or any kind of property
* if executing with the strict option. We check here at runtime as well
* as at compile-time, to handle eval as well as multiple HTML script tags.
*/
/* ES5 10.5 (NB: with subsequent errata). */
jsid id = ATOM_TO_JSID(fun->atom);
JSProperty *prop = NULL;
JSObject *pobj;
JSBool ok = CheckRedeclaration(cx, parent, id, attrs, &pobj, &prop);
if (!ok)
if (!parent->lookupProperty(cx, id, &pobj, &prop))
goto error;
/*
* We deviate from ES3 10.1.3, ES5 10.5, by using JSObject::setProperty not
* JSObject::defineProperty for a function declaration in eval code whose
* id is already bound to a JSPROP_PERMANENT property, to ensure that such
* properties can't be deleted.
*
* We also use JSObject::setProperty for the existing properties of Call
* objects with matching attributes to preserve the internal (JSPropertyOp)
* getters and setters that update the value of the property in the stack
* frame. See bug 467495.
*/
bool doSet = false;
if (prop) {
JS_ASSERT(!(attrs & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)));
JS_ASSERT((attrs == JSPROP_ENUMERATE) == regs.fp->isEvalFrame());
if (attrs == JSPROP_ENUMERATE) {
/* In eval code: assign rather than (re-)define, always. */
doSet = true;
} else if (parent->isCall()) {
JS_ASSERT(parent == pobj);
uintN oldAttrs = ((Shape *) prop)->attributes();
JS_ASSERT(!(oldAttrs & (JSPROP_READONLY | JSPROP_GETTER | JSPROP_SETTER)));
/*
* We may be processing a function sub-statement or declaration in
* function code: we assign rather than redefine if the essential
* JSPROP_PERMANENT (not [[Configurable]] in ES5 terms) attribute
* is not changing (note that JSPROP_ENUMERATE is set for all Call
* object properties).
*/
JS_ASSERT(oldAttrs & attrs & JSPROP_ENUMERATE);
if (oldAttrs & JSPROP_PERMANENT)
doSet = true;
}
}
Value rval = ObjectValue(*obj);
ok = doSet
? parent->setProperty(cx, id, &rval, script->strictModeCode)
: parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs);
if (!ok)
goto error;
do {
/* Steps 5d, 5f. */
if (!prop || pobj != parent) {
if (!parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs))
goto error;
break;
}
/* Step 5e. */
JS_ASSERT(parent->isNative());
Shape *shape = reinterpret_cast<Shape *>(prop);
if (parent->isGlobal()) {
if (shape->configurable()) {
if (!parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs))
goto error;
break;
}
if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
JSAutoByteString bytes;
if (const char *name = js_ValueToPrintable(cx, IdToValue(id), &bytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_REDEFINE_PROP, name);
}
goto error;
}
}
/*
* Non-global properties, and global properties which we aren't simply
* redefining, must be set. First, this preserves their attributes.
* Second, this will produce warnings and/or errors as necessary if the
* specified Call object property is not writable (const).
*/
/* Step 5f. */
if (!parent->setProperty(cx, id, &rval, script->strictModeCode))
goto error;
} while (false);
}
END_CASE(JSOP_DEFFUN)
@ -6267,7 +6259,6 @@ BEGIN_CASE(JSOP_INSTANCEOF)
}
END_CASE(JSOP_INSTANCEOF)
#if JS_HAS_DEBUGGER_KEYWORD
BEGIN_CASE(JSOP_DEBUGGER)
{
JSDebuggerHandler handler = cx->debugHooks->debuggerHandler;
@ -6291,7 +6282,6 @@ BEGIN_CASE(JSOP_DEBUGGER)
}
}
END_CASE(JSOP_DEBUGGER)
#endif /* JS_HAS_DEBUGGER_KEYWORD */
#if JS_HAS_XML_SUPPORT
BEGIN_CASE(JSOP_DEFXMLNS)

View File

@ -38,87 +38,75 @@
*
* ***** END LICENSE BLOCK ***** */
/*
* Keywords used as primary expressions, sharing the TOK_PRIMARY token kind,
* distinguished by opcode.
*/
JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT)
JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT)
JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT)
/* ES5 Keywords. */
JS_KEYWORD(break, TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(case, TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(continue, TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(default, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(delete, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(do, TOK_DO, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(else, TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(export, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT)
JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(for, TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(function, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(if, TOK_IF, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(in, TOK_IN, JSOP_IN, JSVERSION_DEFAULT)
JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_DEFAULT)
JS_KEYWORD(new, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT)
JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT)
JS_KEYWORD(return, TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(switch, TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(this, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT)
JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT)
JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(typeof, TOK_UNARYOP, JSOP_TYPEOF, JSVERSION_DEFAULT)
JS_KEYWORD(var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT)
JS_KEYWORD(void, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT)
JS_KEYWORD(while, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT)
/* ES5 FutureReservedWord keywords. */
JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(export, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
/*
* ES5 reserved keywords with long-implemented behavior, allowed in our
* implementation to ease code migration.
*/
#if JS_HAS_CONST
JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT)
#else
JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_DEFAULT)
#if JS_HAS_RESERVED_JAVA_KEYWORDS
JS_KEYWORD(abstract, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(boolean, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(byte, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(char, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(double, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(final, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(float, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(goto, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(implements, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(int, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(interface, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(long, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(native, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(package, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(private, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(protected, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(public, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(short, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(static, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(synchronized,TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(throws, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(transient, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(volatile, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_RESERVED_ECMA_KEYWORDS
JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_DEBUGGER_KEYWORD
JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_DEFAULT)
#elif JS_HAS_RESERVED_ECMA_KEYWORDS
JS_KEYWORD(debugger, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
#endif
#if JS_HAS_GENERATORS
JS_KEYWORD(yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7)
#endif
#if JS_HAS_BLOCK_SCOPE
JS_KEYWORD(let, TOK_LET, JSOP_NOP, JSVERSION_1_7)
JS_KEYWORD(let, TOK_LET, JSOP_NOP, JSVERSION_1_7)
#else
JS_KEYWORD(let, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7)
#endif
#if JS_HAS_GENERATORS
JS_KEYWORD(yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7)
#else
JS_KEYWORD(yield, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_1_7)
#endif
/* ES5 future reserved keywords in strict mode. */
JS_KEYWORD(implements, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(interface, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(package, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(private, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(protected, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(public, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
JS_KEYWORD(static, TOK_STRICT_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)

View File

@ -902,16 +902,24 @@ obj_valueOf(JSContext *cx, uintN argc, Value *vp)
* principals.
*/
JSBool
js_CheckContentSecurityPolicy(JSContext *cx)
js_CheckContentSecurityPolicy(JSContext *cx, JSObject *scopeobj)
{
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
// CSP is static per document, so if our check said yes before, that
// answer is still valid.
JSObject *global = scopeobj->getGlobal();
Value v = global->getReservedSlot(JSRESERVED_GLOBAL_EVAL_ALLOWED);
if (v.isUndefined()) {
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
// if there are callbacks, make sure that the CSP callback is installed and
// that it permits eval().
if (callbacks && callbacks->contentSecurityPolicyAllows)
return callbacks->contentSecurityPolicyAllows(cx);
// if there are callbacks, make sure that the CSP callback is installed and
// that it permits eval().
v.setBoolean((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
callbacks->contentSecurityPolicyAllows(cx));
return JS_TRUE;
// update the cache in the global object for the result of the security check
js_SetReservedSlot(cx, global, JSRESERVED_GLOBAL_EVAL_ALLOWED, v);
}
return !v.isFalse();
}
/*
@ -1155,7 +1163,7 @@ EvalKernel(JSContext *cx, uintN argc, Value *vp, EvalType evalType, JSStackFrame
* CSP check: Is eval() allowed at all?
* Report errors via CSP is done in the script security mgr.
*/
if (!js_CheckContentSecurityPolicy(cx)) {
if (!js_CheckContentSecurityPolicy(cx, scopeobj)) {
JS_ReportError(cx, "call to eval() blocked by CSP");
return false;
}

View File

@ -1808,7 +1808,7 @@ js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
/* For CSP -- checks if eval() and friends are allowed to run. */
extern JSBool
js_CheckContentSecurityPolicy(JSContext *cx);
js_CheckContentSecurityPolicy(JSContext *cx, JSObject *scopeObj);
/* NB: Infallible. */
extern const char *

View File

@ -4613,12 +4613,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
break;
#endif /* JS_HAS_SHARP_VARS */
#if JS_HAS_DEBUGGER_KEYWORD
case JSOP_DEBUGGER:
js_printf(jp, "\tdebugger;\n");
todo = -2;
break;
#endif /* JS_HAS_DEBUGGER_KEYWORD */
#if JS_HAS_XML_SUPPORT
case JSOP_STARTXML:
@ -5100,6 +5098,9 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v_in,
pc = fp->hasImacropc() ? fp->imacropc() : cx->regs->pc;
JS_ASSERT(script->code <= pc && pc < script->code + script->length);
if (pc < script->main)
goto do_fallback;
if (spindex != JSDVG_IGNORE_STACK) {
jsbytecode **pcstack;

View File

@ -301,6 +301,8 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc)
}
funbox->level = tc->staticLevel;
funbox->tcflags = (TCF_IN_FUNCTION | (tc->flags & (TCF_COMPILE_N_GO | TCF_STRICT_MODE_CODE)));
if (tc->innermostWith)
funbox->tcflags |= TCF_IN_WITH;
return funbox;
}
@ -311,6 +313,16 @@ JSFunctionBox::joinable() const
!(tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME));
}
bool
JSFunctionBox::inAnyDynamicScope() const
{
for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) {
if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_CALLS_EVAL))
return true;
}
return false;
}
bool
JSFunctionBox::shouldUnbrand(uintN methods, uintN slowMethods) const
{
@ -2464,6 +2476,9 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32 *tcflags)
FUN_METER(allfun);
if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
FUN_METER(heavy);
} else if (funbox->inAnyDynamicScope()) {
JS_ASSERT(!FUN_NULL_CLOSURE(fun));
FUN_METER(indynamicscope);
} else if (pn->pn_type != TOK_UPVARS) {
/*
* No lexical dependencies => null closure, for best performance.
@ -6188,7 +6203,6 @@ Parser::statement()
pn->pn_type = TOK_SEMI;
return pn;
#if JS_HAS_DEBUGGER_KEYWORD
case TOK_DEBUGGER:
pn = NullaryNode::create(tc);
if (!pn)
@ -6196,7 +6210,6 @@ Parser::statement()
pn->pn_type = TOK_DEBUGGER;
tc->flags |= TCF_FUN_HEAVYWEIGHT;
break;
#endif /* JS_HAS_DEBUGGER_KEYWORD */
#if JS_HAS_XML_SUPPORT
case TOK_DEFAULT:

View File

@ -976,6 +976,12 @@ struct JSFunctionBox : public JSObjectBox
bool joinable() const;
/*
* True if this function is inside the scope of a with-statement, an E4X
* filter-expression, or a function that uses direct eval.
*/
bool inAnyDynamicScope() const;
/*
* Unbrand an object being initialized or constructed if any method cannot
* be joined to one compiler-created null closure shared among N different

View File

@ -99,6 +99,7 @@ JS_PROTO(Float32Array, 34, js_InitTypedArrayClasses)
JS_PROTO(Float64Array, 35, js_InitTypedArrayClasses)
JS_PROTO(Uint8ClampedArray, 36, js_InitTypedArrayClasses)
JS_PROTO(Proxy, 37, js_InitProxyClass)
JS_PROTO(AnyName, 38, js_InitNullClass)
#undef XML_INIT
#undef NAMESPACE_INIT

View File

@ -1043,14 +1043,35 @@ TokenStream::getTokenInternal()
!(flags & TSF_KEYWORD_IS_NAME) &&
(kw = FindKeyword(tokenbuf.begin(), tokenbuf.length()))) {
if (kw->tokentype == TOK_RESERVED) {
if (!ReportCompileErrorNumber(cx, this, NULL, JSREPORT_WARNING | JSREPORT_STRICT,
if (!ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR,
JSMSG_RESERVED_ID, kw->chars)) {
goto error;
}
} else if (kw->version <= VersionNumber(version)) {
tt = kw->tokentype;
tp->t_op = (JSOp) kw->op;
goto out;
} else if (kw->tokentype == TOK_STRICT_RESERVED) {
if (isStrictMode()
? !ReportStrictModeError(cx, this, NULL, NULL, JSMSG_RESERVED_ID, kw->chars)
: !ReportCompileErrorNumber(cx, this, NULL,
JSREPORT_STRICT | JSREPORT_WARNING,
JSMSG_RESERVED_ID, kw->chars)) {
goto error;
}
} else {
if (kw->version <= VersionNumber(version)) {
tt = kw->tokentype;
tp->t_op = (JSOp) kw->op;
goto out;
}
/*
* let/yield are a Mozilla extension starting in JS1.7. If we
* aren't parsing for a version supporting these extensions,
* conform to ES5 and forbid these names in strict mode.
*/
if ((kw->tokentype == TOK_LET || kw->tokentype == TOK_YIELD) &&
!ReportStrictModeError(cx, this, NULL, NULL, JSMSG_RESERVED_ID, kw->chars))
{
goto error;
}
}
}

View File

@ -144,6 +144,7 @@ enum TokenKind {
of definitions paired with a parse
tree full of uses of those names */
TOK_RESERVED, /* reserved keywords */
TOK_STRICT_RESERVED, /* reserved keywords in strict mode */
TOK_LIMIT /* domain size */
};

View File

@ -12458,7 +12458,7 @@ TraceRecorder::recordInitPropertyOp(jsbytecode op)
LIns* v_ins = get(&v);
JSAtom* atom = atoms[GET_INDEX(cx->regs->pc)];
jsid id = ATOM_TO_JSID(atom);
jsid id = js_CheckForStringIndex(ATOM_TO_JSID(atom));
// If obj already has this property (because JSOP_NEWOBJECT already set its
// shape or because the id appears more than once in the initializer), just
@ -14978,6 +14978,13 @@ TraceRecorder::record_JSOP_POPN()
return ARECORD_CONTINUE;
}
static inline bool
IsFindableCallObj(JSObject *obj)
{
return obj->isCall() &&
(obj->callIsForEval() || obj->getCallObjCalleeFunction()->isHeavyweight());
}
/*
* Generate LIR to reach |obj2| from |obj| by traversing the scope chain. The
* generated code also ensures that any call objects found have not changed shape.
@ -15019,13 +15026,10 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target
for (;;) {
if (searchObj != globalObj) {
Class* clasp = searchObj->getClass();
if (clasp == &js_BlockClass) {
if (searchObj->isBlock())
foundBlockObj = true;
} else if (clasp == &js_CallClass &&
searchObj->getCallObjCalleeFunction()->isHeavyweight()) {
else if (IsFindableCallObj(searchObj))
foundCallObj = true;
}
}
if (searchObj == targetObj)
@ -15054,8 +15058,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target
// We must guard on the shape of all call objects for heavyweight functions
// that we traverse on the scope chain: if the shape changes, a variable with
// the same name may have been inserted in the scope chain.
if (obj->isCall() &&
obj->getCallObjCalleeFunction()->isHeavyweight()) {
if (IsFindableCallObj(obj)) {
if (!exit)
exit = snapshot(BRANCH_EXIT);
guard(true,

View File

@ -46,6 +46,7 @@
#include "jstypes.h"
#include <stdlib.h>
#include <string.h>
JS_BEGIN_EXTERN_C

View File

@ -89,7 +89,6 @@
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
#define JS_HAS_XDR 0 /* has XDR API and internal support */
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
@ -117,7 +116,6 @@
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
#define JS_HAS_XDR 1 /* has XDR API and internal support */
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
@ -141,7 +139,6 @@
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
#define JS_HAS_XDR 1 /* has XDR API and internal support */
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
@ -165,7 +162,6 @@
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
#define JS_HAS_XDR 1 /* has XDR API and internal support */
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
@ -189,7 +185,6 @@
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
#define JS_HAS_XDR 1 /* has XDR API and internal support */
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
@ -210,10 +205,6 @@
#endif
/* Features that are present in all versions. */
#define JS_HAS_RESERVED_JAVA_KEYWORDS 1
#define JS_HAS_RESERVED_ECMA_KEYWORDS 1
/* Support for JS_NewGlobalObject. */
#define JS_HAS_NEW_GLOBAL_OBJECT 1

View File

@ -140,7 +140,6 @@ static struct {
* Random utilities and global functions.
*/
const char js_AttributeName_str[] = "AttributeName";
const char js_AnyName_str[] = "AnyName";
const char js_isXMLName_str[] = "isXMLName";
const char js_XMLList_str[] = "XMLList";
const char js_localName_str[] = "localName";
@ -208,13 +207,6 @@ DEFINE_GETTER(NamePrefix_getter,
DEFINE_GETTER(NameURI_getter,
if (obj->getClass() == &js_NamespaceClass) *vp = obj->getNameURIVal())
static void
namespace_finalize(JSContext *cx, JSObject *obj)
{
if (obj->compartment()->functionNamespaceObject == obj)
obj->compartment()->functionNamespaceObject = NULL;
}
static JSBool
namespace_equality(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
{
@ -240,7 +232,7 @@ JS_FRIEND_DATA(Class) js_NamespaceClass = {
EnumerateStub,
ResolveStub,
ConvertStub,
namespace_finalize,
FinalizeStub,
NULL, /* reserved0 */
NULL, /* checkAccess */
NULL, /* call */
@ -314,14 +306,6 @@ DEFINE_GETTER(QNameLocalName_getter,
if (obj->getClass() == &js_QNameClass)
*vp = obj->getQNameLocalNameVal())
static void
anyname_finalize(JSContext* cx, JSObject* obj)
{
/* Make sure the next call to js_GetAnyName doesn't try to use obj. */
if (obj->compartment()->anynameObject == obj)
obj->compartment()->anynameObject = NULL;
}
static JSBool
qname_identity(JSObject *qna, JSObject *qnb)
{
@ -393,7 +377,8 @@ JS_FRIEND_DATA(Class) js_AttributeNameClass = {
PropertyStub, /* setProperty */
EnumerateStub,
ResolveStub,
ConvertStub
ConvertStub,
FinalizeStub
};
JS_FRIEND_DATA(Class) js_AnyNameClass = {
@ -408,7 +393,7 @@ JS_FRIEND_DATA(Class) js_AnyNameClass = {
EnumerateStub,
ResolveStub,
ConvertStub,
anyname_finalize
FinalizeStub
};
#define QNAME_ATTRS (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
@ -6363,7 +6348,7 @@ xml_replace(JSContext *cx, uintN argc, jsval *vp)
bool haveIndex;
if (argc == 0) {
haveIndex = true;
haveIndex = false;
} else {
if (!js_IdValIsIndex(cx, vp[2], &index, &haveIndex))
return JS_FALSE;
@ -7185,15 +7170,14 @@ js_InitXMLClasses(JSContext *cx, JSObject *obj)
JSBool
js_GetFunctionNamespace(JSContext *cx, Value *vp)
{
JSObject *obj;
JSLinearString *prefix, *uri;
JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
obj = cx->compartment->functionNamespaceObject;
if (!obj) {
*vp = global->getReservedSlot(JSRESERVED_GLOBAL_FUNCTION_NS);
if (vp->isUndefined()) {
JSRuntime *rt = cx->runtime;
prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION];
uri = rt->atomState.functionNamespaceURIAtom;
obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
JSLinearString *prefix = rt->atomState.typeAtoms[JSTYPE_FUNCTION];
JSLinearString *uri = rt->atomState.functionNamespaceURIAtom;
JSObject *obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
if (!obj)
return false;
@ -7202,13 +7186,14 @@ js_GetFunctionNamespace(JSContext *cx, Value *vp)
* Namespace.prototype is not detectable, as there is no way to
* refer to this instance in scripts. When used to qualify method
* names, its prefix and uri references are copied to the QName.
* The parent remains set and links back to global.
*/
obj->clearProto();
obj->clearParent();
cx->compartment->functionNamespaceObject = obj;
vp->setObject(*obj);
if (!js_SetReservedSlot(cx, global, JSRESERVED_GLOBAL_FUNCTION_NS, *vp))
return false;
}
vp->setObject(*obj);
return true;
}
@ -7351,28 +7336,25 @@ js_ValueToXMLString(JSContext *cx, const Value &v)
JSBool
js_GetAnyName(JSContext *cx, jsid *idp)
{
JSObject *obj = cx->compartment->anynameObject;
if (!obj) {
/*
* Avoid entraining any Object.prototype found via cx's scope
* chain or global object for this internal AnyName object.
*/
obj = NewNonFunction<WithProto::Given>(cx, &js_AnyNameClass, NULL, NULL);
JSObject *global = cx->hasfp() ? cx->fp()->scopeChain().getGlobal() : cx->globalObject;
Value v = global->getReservedSlot(JSProto_AnyName);
if (v.isUndefined()) {
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &js_AnyNameClass, NULL, global);
if (!obj)
return false;
JS_ASSERT(!obj->getProto());
JSRuntime *rt = cx->runtime;
InitXMLQName(obj, rt->emptyString, rt->emptyString,
ATOM_TO_STRING(rt->atomState.starAtom));
METER(xml_stats.qname);
JS_ASSERT(!obj->getProto());
JS_ASSERT(!obj->getParent());
cx->compartment->anynameObject = obj;
v.setObject(*obj);
if (!js_SetReservedSlot(cx, global, JSProto_AnyName, v))
return false;
}
*idp = OBJECT_TO_JSID(obj);
*idp = OBJECT_TO_JSID(&v.toObject());
return true;
}

View File

@ -71,10 +71,8 @@ using namespace js::mjit::ic;
#define RETURN_IF_OOM(retval) \
JS_BEGIN_MACRO \
if (oomInVector || masm.oom() || stubcc.masm.oom()) { \
js_ReportOutOfMemory(cx); \
if (oomInVector || masm.oom() || stubcc.masm.oom()) \
return retval; \
} \
JS_END_MACRO
#if defined(JS_METHODJIT_SPEW)
@ -151,11 +149,14 @@ mjit::Compiler::compile()
return status;
}
#define CHECK_STATUS(expr) \
JS_BEGIN_MACRO \
CompileStatus status_ = (expr); \
if (status_ != Compile_Okay) \
return status_; \
#define CHECK_STATUS(expr) \
JS_BEGIN_MACRO \
CompileStatus status_ = (expr); \
if (status_ != Compile_Okay) { \
if (oomInVector || masm.oom() || stubcc.masm.oom()) \
js_ReportOutOfMemory(cx); \
return status_; \
} \
JS_END_MACRO
CompileStatus
@ -169,8 +170,10 @@ mjit::Compiler::performCompilation(JITScript **jitp)
analysis.analyze(cx, script);
if (analysis.OOM())
if (analysis.OOM()) {
js_ReportOutOfMemory(cx);
return Compile_Error;
}
if (analysis.failed()) {
JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n");
return Compile_Abort;
@ -178,12 +181,16 @@ mjit::Compiler::performCompilation(JITScript **jitp)
this->analysis = &analysis;
if (!frame.init())
return Compile_Abort;
if (!frame.init()) {
js_ReportOutOfMemory(cx);
return Compile_Error;
}
jumpMap = (Label *)cx->malloc(sizeof(Label) * script->length);
if (!jumpMap)
if (!jumpMap) {
js_ReportOutOfMemory(cx);
return Compile_Error;
}
#ifdef DEBUG
for (uint32 i = 0; i < script->length; i++)
jumpMap[i] = Label();
@ -401,10 +408,17 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
jumpTableOffsets.length() * sizeof(void *);
JSC::ExecutablePool *execPool = getExecPool(script, totalSize);
if (!execPool)
return Compile_Abort;
if (!execPool) {
js_ReportOutOfMemory(cx);
return Compile_Error;
}
uint8 *result = (uint8 *)execPool->alloc(totalSize);
if (!result) {
execPool->release();
js_ReportOutOfMemory(cx);
return Compile_Error;
}
JSC::ExecutableAllocator::makeWritable(result, totalSize);
masm.executableCopy(result);
stubcc.masm.executableCopy(result + masm.size());
@ -438,6 +452,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
uint8 *cursor = (uint8 *)cx->calloc(totalBytes);
if (!cursor) {
execPool->release();
js_ReportOutOfMemory(cx);
return Compile_Error;
}
@ -1471,7 +1486,8 @@ mjit::Compiler::generateMethod()
masm.jump(Registers::ReturnReg);
#else
jsop_tableswitch(PC);
if (!jsop_tableswitch(PC))
return Compile_Error;
#endif
PC += js_GetVariableBytecodeLength(PC);
break;
@ -4808,11 +4824,12 @@ mjit::Compiler::constructThis()
return true;
}
void
bool
mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
{
#if defined JS_CPU_ARM
JS_NOT_REACHED("Implement jump(BaseIndex) for ARM");
return true;
#else
jsbytecode *originalPC = pc;
@ -4832,7 +4849,7 @@ mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
*/
if (numJumps == 0) {
frame.pop();
return;
return true;
}
FrameEntry *fe = frame.peek(-1);
@ -4844,7 +4861,7 @@ mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
INLINE_STUBCALL(stubs::TableSwitch);
frame.pop();
masm.jump(Registers::ReturnReg);
return;
return true;
}
RegisterID dataReg;
@ -4890,7 +4907,7 @@ mjit::Compiler::jsop_tableswitch(jsbytecode *pc)
stubcc.masm.jump(Registers::ReturnReg);
}
frame.pop();
jumpAndTrace(defaultCase, originalPC + defaultTarget);
return jumpAndTrace(defaultCase, originalPC + defaultTarget);
#endif
}

View File

@ -461,7 +461,7 @@ class Compiler : public BaseCompiler
void leaveBlock();
void emitEval(uint32 argc);
void jsop_arguments();
void jsop_tableswitch(jsbytecode *pc);
bool jsop_tableswitch(jsbytecode *pc);
void jsop_forprop(JSAtom *atom);
void jsop_forname(JSAtom *atom);
void jsop_forgname(JSAtom *atom);

View File

@ -160,7 +160,8 @@ ic::SetGlobalName(VMFrame &f, ic::MICInfo *ic)
const Shape *shape = obj->nativeLookup(id);
if (!shape ||
!shape->hasDefaultGetterOrIsMethod() ||
shape->isMethod() ||
!shape->hasDefaultSetter() ||
!shape->writable() ||
!shape->hasSlot())
{

View File

@ -723,7 +723,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
*/
obj2 = &fp->scopeChain();
} else {
JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
JS_ASSERT(!fun->isFlatClosure());
obj2 = GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
if (!obj2)
@ -760,62 +760,54 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
*/
JSObject *parent = &fp->varobj(cx);
/*
* Check for a const property of the same name -- or any kind of property
* if executing with the strict option. We check here at runtime as well
* as at compile-time, to handle eval as well as multiple HTML script tags.
*/
/* ES5 10.5 (NB: with subsequent errata). */
jsid id = ATOM_TO_JSID(fun->atom);
JSProperty *prop = NULL;
JSObject *pobj;
JSBool ok = CheckRedeclaration(cx, parent, id, attrs, &pobj, &prop);
if (!ok)
if (!parent->lookupProperty(cx, id, &pobj, &prop))
THROW();
/*
* We deviate from ES3 10.1.3, ES5 10.5, by using JSObject::setProperty not
* JSObject::defineProperty for a function declaration in eval code whose
* id is already bound to a JSPROP_PERMANENT property, to ensure that such
* properties can't be deleted.
*
* We also use JSObject::setProperty for the existing properties of Call
* objects with matching attributes to preserve the internal (JSPropertyOp)
* getters and setters that update the value of the property in the stack
* frame. See bug 467495.
*/
bool doSet = false;
if (prop) {
JS_ASSERT(!(attrs & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)));
JS_ASSERT((attrs == JSPROP_ENUMERATE) == fp->isEvalFrame());
if (attrs == JSPROP_ENUMERATE) {
/* In eval code: assign rather than (re-)define, always. */
doSet = true;
} else if (parent->isCall()) {
JS_ASSERT(parent == pobj);
uintN oldAttrs = ((Shape *) prop)->attributes();
JS_ASSERT(!(oldAttrs & (JSPROP_READONLY | JSPROP_GETTER | JSPROP_SETTER)));
/*
* We may be processing a function sub-statement or declaration in
* function code: we assign rather than redefine if the essential
* JSPROP_PERMANENT (not [[Configurable]] in ES5 terms) attribute
* is not changing (note that JSPROP_ENUMERATE is set for all Call
* object properties).
*/
JS_ASSERT(oldAttrs & attrs & JSPROP_ENUMERATE);
if (oldAttrs & JSPROP_PERMANENT)
doSet = true;
}
}
Value rval = ObjectValue(*obj);
ok = doSet
? parent->setProperty(cx, id, &rval, strict)
: parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs);
if (!ok)
THROW();
do {
/* Steps 5d, 5f. */
if (!prop || pobj != parent) {
if (!parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs))
THROW();
break;
}
/* Step 5e. */
JS_ASSERT(parent->isNative());
Shape *shape = reinterpret_cast<Shape *>(prop);
if (parent->isGlobal()) {
if (shape->configurable()) {
if (!parent->defineProperty(cx, id, rval, PropertyStub, PropertyStub, attrs))
THROW();
break;
}
if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
JSAutoByteString bytes;
if (const char *name = js_ValueToPrintable(cx, IdToValue(id), &bytes)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_REDEFINE_PROP, name);
}
THROW();
}
}
/*
* Non-global properties, and global properties which we aren't simply
* redefining, must be set. First, this preserves their attributes.
* Second, this will produce warnings and/or errors as necessary if the
* specified Call object property is not writable (const).
*/
/* Step 5f. */
if (!parent->setProperty(cx, id, &rval, strict))
THROW();
} while (false);
}
template void JS_FASTCALL stubs::DefFun<true>(VMFrame &f, JSFunction *fun);

View File

@ -1055,6 +1055,37 @@ Load(JSContext *cx, uintN argc, jsval *vp)
return JS_TRUE;
}
static JSBool
Evaluate(JSContext *cx, uintN argc, jsval *vp)
{
if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
(argc != 1) ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_INVALID_ARGS,
"evaluate");
return false;
}
JSString *code = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]);
size_t codeLength;
const jschar *codeChars = JS_GetStringCharsAndLength(cx, code, &codeLength);
if (!codeChars)
return false;
JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
if (!thisobj)
return false;
if ((JS_GET_CLASS(cx, thisobj)->flags & JSCLASS_IS_GLOBAL) != JSCLASS_IS_GLOBAL) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
"this-value passed to evaluate()", "not a global object");
return false;
}
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_EvaluateUCScript(cx, thisobj, codeChars, codeLength, "@evaluate", 0, NULL);
}
/*
* function readline()
* Provides a hook for scripts to read a line from stdin.
@ -4265,12 +4296,12 @@ StringStats(JSContext *cx, uintN argc, jsval *vp)
return true;
}
/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
static JSFunctionSpec shell_functions[] = {
JS_FN("version", Version, 0,0),
JS_FN("revertVersion", RevertVersion, 0,0),
JS_FN("options", Options, 0,0),
JS_FN("load", Load, 1,0),
JS_FN("evaluate", Evaluate, 1,0),
JS_FN("readline", ReadLine, 0,0),
JS_FN("print", Print, 0,0),
JS_FN("putstr", PutStr, 0,0),
@ -4372,6 +4403,7 @@ static const char *const shell_help_messages[] = {
"revertVersion() Revert previously set version number",
"options([option ...]) Get or toggle JavaScript options",
"load(['foo.js' ...]) Load files named by string arguments",
"evaluate(code) Evaluate code as though it were the contents of a file",
"readline() Read a single line from stdin",
"print([exp ...]) Evaluate and print expressions",
"putstr([exp]) Evaluate and print expression without newline",

View File

@ -44,39 +44,39 @@ var expect = '';
printBugNumber(BUGNUMBER);
START(summary);
actual = ToString((function () { return <xml/>; }));
actual = ConvertToString((function () { return <xml/>; }));
expect = 'function () { return <xml/>;}';
TEST(1, expect, actual);
actual = ToString((function () { return <xml></xml>; }));
actual = ConvertToString((function () { return <xml></xml>; }));
expect = 'function () { return <xml></xml>;}';
TEST(2, expect, actual);
actual = ToString((function () { return <xml><morexml/></xml>; }));
actual = ConvertToString((function () { return <xml><morexml/></xml>; }));
expect = 'function () { return <xml><morexml/></xml>;}';
TEST(3, expect, actual);
actual = ToString((function (k) { return <xml>{k}</xml>; }));
actual = ConvertToString((function (k) { return <xml>{k}</xml>; }));
expect = 'function (k) { return <xml>{k}</xml>;}';
TEST(4, expect, actual);
actual = ToString((function (k) { return <{k}/>; }));
actual = ConvertToString((function (k) { return <{k}/>; }));
expect = 'function (k) { return <{k}/>;}';
TEST(5, expect, actual);
actual = ToString((function (k) { return <{k}>{k}</{k}>; }));
actual = ConvertToString((function (k) { return <{k}>{k}</{k}>; }));
expect = 'function (k) { return <{k}>{k}</{k}>;}';
TEST(6, expect, actual);
actual = ToString((function (k) { return <{k}
{k}={k} {"k"}={k + "world"}><{k + "k"}/></{k}>; }));
actual = ConvertToString((function (k) { return <{k}
{k}={k} {"k"}={k + "world"}><{k + "k"}/></{k}>; }));
expect = 'function (k) ' +
'{ return <{k} {k}={k} {"k"}={k + "world"}><{k + "k"}/></{k}>;}';
TEST(7, expect, actual);
END();
function ToString(f)
function ConvertToString(f)
{
return f.toString().replace(/\n/g, '').replace(/[ ]+/g, ' ');
}

View File

@ -53,3 +53,4 @@ skip script regress-324422-2.js # slow
skip script regress-324688.js # bug 528404 - disable due to random timeouts
script regress-336921.js
script regress-376773.js
script regress-621464.js

View File

@ -0,0 +1,51 @@
/* -*- Mode: java; tab-width:8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JavaScript Engine testing utilities.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Andrew Drake
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var BUGNUMBER = 621464;
var summary = '<x>a</x>.replace() == <x>a</x>';
printBugNumber(BUGNUMBER);
START(summary);
var expected = <x>a</x>;
var actual = <x>a</x>.replace();
TEST(0, expected, actual);
END();

View File

@ -53,22 +53,22 @@ startTest();
writeHeaderToLog( SECTION + " "+ TITLE);
new TestCase( SECTION,
"ToString.call( this, this )",
"ConvertToString.call(this, this)",
GLOBAL,
ToString.call( this, this ) );
ConvertToString.call(this, this));
new TestCase( SECTION,
"ToString.call( Boolean, Boolean.prototype )",
"ConvertToString.call(Boolean, Boolean.prototype)",
"false",
ToString.call( Boolean, Boolean.prototype ) );
ConvertToString.call(Boolean, Boolean.prototype));
new TestCase( SECTION,
"ToString.call( Boolean, Boolean.prototype.valueOf() )",
"ConvertToString.call(Boolean, Boolean.prototype.valueOf())",
"false",
ToString.call( Boolean, Boolean.prototype.valueOf() ) );
ConvertToString.call(Boolean, Boolean.prototype.valueOf()));
test();
function ToString( obj ) {
function ConvertToString(obj) {
return obj +"";
}

View File

@ -0,0 +1,343 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 577325;
var summary = 'Implement the ES5 algorithm for processing function statements';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var outer, desc;
///////////////////////////////////////////////////
// Function definitions over accessor properties //
///////////////////////////////////////////////////
var getCalled, setCalled;
// configurable properties get blown away
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc1",
{
get: function() { getCalled = true; throw "FAIL get 1"; },
set: function(v) { setCalled = true; throw "FAIL set 1 " + v; },
configurable: true,
enumerable: false
});
// does not throw
outer = undefined;
eval("function acc1() { throw 'FAIL redefined 1'; } outer = acc1;");
assertEq(getCalled, false);
assertEq(setCalled, false);
assertEq(typeof acc1, "function");
assertEq(acc1, outer);
desc = Object.getOwnPropertyDescriptor(this, "acc1");
assertEq(desc.value, acc1);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc2",
{
get: function() { getCalled = true; throw "FAIL get 2"; },
set: function(v) { setCalled = true; throw "FAIL set 2 " + v; },
configurable: true,
enumerable: true
});
// does not throw
outer = undefined;
eval("function acc2() { throw 'FAIL redefined 2'; } outer = acc2;");
assertEq(getCalled, false);
assertEq(setCalled, false);
assertEq(typeof acc2, "function");
assertEq(acc2, outer);
desc = Object.getOwnPropertyDescriptor(this, "acc2");
assertEq(desc.value, acc2);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
// non-configurable properties produce a TypeError
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc3",
{
get: function() { getCalled = true; throw "FAIL get 3"; },
set: function(v) { setCalled = true; throw "FAIL set 3 " + v; },
configurable: false,
enumerable: true
});
outer = undefined;
try
{
eval("function acc3() { throw 'FAIL redefined 3'; }; outer = acc3");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, enumerable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, enumerable accessor, must throw a TypeError " +
"per ES5+errata: " + e);
desc = Object.getOwnPropertyDescriptor(this, "acc3");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set, "function");
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
assertEq(outer, undefined);
assertEq(getCalled, false);
assertEq(setCalled, false);
}
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc4",
{
get: function() { getCalled = true; throw "FAIL get 4"; },
set: function(v) { setCalled = true; throw "FAIL set 4 " + v; },
configurable: false,
enumerable: false
});
outer = undefined;
try
{
eval("function acc4() { throw 'FAIL redefined 4'; }; outer = acc4");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable accessor, must throw a " +
"TypeError per ES5+errata: " + e);
desc = Object.getOwnPropertyDescriptor(this, "acc4");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set, "function");
assertEq(desc.enumerable, false);
assertEq(desc.configurable, false);
assertEq(outer, undefined);
assertEq(getCalled, false);
assertEq(setCalled, false);
}
///////////////////////////////////////////////
// Function definitions over data properties //
///////////////////////////////////////////////
// configurable properties, regardless of other attributes, get blown away
Object.defineProperty(this, "data1",
{
configurable: true,
enumerable: true,
writable: true,
value: "data1"
});
outer = undefined;
eval("function data1() { return 'data1 function'; } outer = data1;");
assertEq(typeof data1, "function");
assertEq(data1, outer);
desc = Object.getOwnPropertyDescriptor(this, "data1");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data1);
Object.defineProperty(this, "data2",
{
configurable: true,
enumerable: true,
writable: false,
value: "data2"
});
outer = undefined;
eval("function data2() { return 'data2 function'; } outer = data2;");
assertEq(typeof data2, "function");
assertEq(data2, outer);
desc = Object.getOwnPropertyDescriptor(this, "data2");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data2);
Object.defineProperty(this, "data3",
{
configurable: true,
enumerable: false,
writable: true,
value: "data3"
});
outer = undefined;
eval("function data3() { return 'data3 function'; } outer = data3;");
assertEq(typeof data3, "function");
assertEq(data3, outer);
desc = Object.getOwnPropertyDescriptor(this, "data3");
assertEq(desc.configurable, true);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data3);
Object.defineProperty(this, "data4",
{
configurable: true,
enumerable: false,
writable: false,
value: "data4"
});
outer = undefined;
eval("function data4() { return 'data4 function'; } outer = data4;");
assertEq(typeof data4, "function");
assertEq(data4, outer);
desc = Object.getOwnPropertyDescriptor(this, "data4");
assertEq(desc.value, data4);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
// non-configurable data properties are trickier
Object.defineProperty(this, "data5",
{
configurable: false,
enumerable: true,
writable: true,
value: "data5"
});
outer = undefined;
eval("function data5() { return 'data5 function'; } outer = data5;");
assertEq(typeof data5, "function");
assertEq(data5, outer);
desc = Object.getOwnPropertyDescriptor(this, "data5");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data5);
Object.defineProperty(this, "data6",
{
configurable: false,
enumerable: true,
writable: false,
value: "data6"
});
outer = undefined;
try
{
eval("function data6() { return 'data6 function'; } outer = data6;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, enumerable, non-writable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, enumerable, non-writable data property, must " +
"throw a TypeError per ES5+errata: " + e);
assertEq(data6, "data6");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data6");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, false);
assertEq(desc.value, "data6");
}
Object.defineProperty(this, "data7",
{
configurable: false,
enumerable: false,
writable: true,
value: "data7"
});
outer = undefined;
try
{
eval("function data7() { return 'data7 function'; } outer = data7;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, writable data" +
"property");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, writable data property, must " +
"throw a TypeError per ES5+errata: " + e);
assertEq(data7, "data7");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data7");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
assertEq(desc.value, "data7");
}
Object.defineProperty(this, "data8",
{
configurable: false,
enumerable: false,
writable: false,
value: "data8"
});
outer = undefined;
try
{
eval("function data8() { return 'data8 function'; } outer = data8;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, non-writable data" +
"property");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, non-writable data property, " +
"must throw a TypeError per ES5+errata: " + e);
assertEq(data8, "data8");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data8");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, false);
assertEq(desc.writable, false);
assertEq(desc.value, "data8");
}
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

View File

@ -0,0 +1,343 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 577325;
var summary = 'Implement the ES5 algorithm for processing function statements';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var outer, desc;
///////////////////////////////////////////////////
// Function definitions over accessor properties //
///////////////////////////////////////////////////
var getCalled, setCalled;
// configurable properties get blown away
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc1",
{
get: function() { getCalled = true; throw "FAIL get 1"; },
set: function(v) { setCalled = true; throw "FAIL set 1 " + v; },
configurable: true,
enumerable: false
});
// does not throw
outer = undefined;
evaluate("function acc1() { throw 'FAIL redefined 1'; } outer = acc1;");
assertEq(getCalled, false);
assertEq(setCalled, false);
assertEq(typeof acc1, "function");
assertEq(acc1, outer);
desc = Object.getOwnPropertyDescriptor(this, "acc1");
assertEq(desc.value, acc1);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc2",
{
get: function() { getCalled = true; throw "FAIL get 2"; },
set: function(v) { setCalled = true; throw "FAIL set 2 " + v; },
configurable: true,
enumerable: true
});
// does not throw
outer = undefined;
evaluate("function acc2() { throw 'FAIL redefined 2'; } outer = acc2;");
assertEq(getCalled, false);
assertEq(setCalled, false);
assertEq(typeof acc2, "function");
assertEq(acc2, outer);
desc = Object.getOwnPropertyDescriptor(this, "acc2");
assertEq(desc.value, acc2);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
// non-configurable properties produce a TypeError
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc3",
{
get: function() { getCalled = true; throw "FAIL get 3"; },
set: function(v) { setCalled = true; throw "FAIL set 3 " + v; },
configurable: false,
enumerable: true
});
outer = undefined;
try
{
evaluate("function acc3() { throw 'FAIL redefined 3'; }; outer = acc3");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, enumerable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, enumerable accessor, must throw a TypeError " +
"per ES5+errata: " + e);
desc = Object.getOwnPropertyDescriptor(this, "acc3");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set, "function");
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
assertEq(outer, undefined);
assertEq(getCalled, false);
assertEq(setCalled, false);
}
getCalled = false, setCalled = false;
Object.defineProperty(this, "acc4",
{
get: function() { getCalled = true; throw "FAIL get 4"; },
set: function(v) { setCalled = true; throw "FAIL set 4 " + v; },
configurable: false,
enumerable: false
});
outer = undefined;
try
{
evaluate("function acc4() { throw 'FAIL redefined 4'; }; outer = acc4");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable accessor, must throw a " +
"TypeError per ES5+errata: " + e);
desc = Object.getOwnPropertyDescriptor(this, "acc4");
assertEq(typeof desc.get, "function");
assertEq(typeof desc.set, "function");
assertEq(desc.enumerable, false);
assertEq(desc.configurable, false);
assertEq(outer, undefined);
assertEq(getCalled, false);
assertEq(setCalled, false);
}
///////////////////////////////////////////////
// Function definitions over data properties //
///////////////////////////////////////////////
// configurable properties, regardless of other attributes, get blown away
Object.defineProperty(this, "data1",
{
configurable: true,
enumerable: true,
writable: true,
value: "data1"
});
outer = undefined;
evaluate("function data1() { return 'data1 function'; } outer = data1;");
assertEq(typeof data1, "function");
assertEq(data1, outer);
desc = Object.getOwnPropertyDescriptor(this, "data1");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data1);
Object.defineProperty(this, "data2",
{
configurable: true,
enumerable: true,
writable: false,
value: "data2"
});
outer = undefined;
evaluate("function data2() { return 'data2 function'; } outer = data2;");
assertEq(typeof data2, "function");
assertEq(data2, outer);
desc = Object.getOwnPropertyDescriptor(this, "data2");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data2);
Object.defineProperty(this, "data3",
{
configurable: true,
enumerable: false,
writable: true,
value: "data3"
});
outer = undefined;
evaluate("function data3() { return 'data3 function'; } outer = data3;");
assertEq(typeof data3, "function");
assertEq(data3, outer);
desc = Object.getOwnPropertyDescriptor(this, "data3");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data3);
Object.defineProperty(this, "data4",
{
configurable: true,
enumerable: false,
writable: false,
value: "data4"
});
outer = undefined;
evaluate("function data4() { return 'data4 function'; } outer = data4;");
assertEq(typeof data4, "function");
assertEq(data4, outer);
desc = Object.getOwnPropertyDescriptor(this, "data4");
assertEq(desc.value, data4);
assertEq(desc.writable, true);
assertEq(desc.enumerable, true);
assertEq(desc.configurable, false);
// non-configurable data properties are trickier
Object.defineProperty(this, "data5",
{
configurable: false,
enumerable: true,
writable: true,
value: "data5"
});
outer = undefined;
evaluate("function data5() { return 'data5 function'; } outer = data5;");
assertEq(typeof data5, "function");
assertEq(data5, outer);
desc = Object.getOwnPropertyDescriptor(this, "data5");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, data5);
Object.defineProperty(this, "data6",
{
configurable: false,
enumerable: true,
writable: false,
value: "data6"
});
outer = undefined;
try
{
evaluate("function data6() { return 'data6 function'; } outer = data6;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, enumerable, non-writable accessor");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, enumerable, non-writable data property, must " +
"throw a TypeError per ES5+errata: " + e);
assertEq(data6, "data6");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data6");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, true);
assertEq(desc.writable, false);
assertEq(desc.value, "data6");
}
Object.defineProperty(this, "data7",
{
configurable: false,
enumerable: false,
writable: true,
value: "data7"
});
outer = undefined;
try
{
evaluate("function data7() { return 'data7 function'; } outer = data7;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, writable data" +
"property");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, writable data property, must " +
"throw a TypeError per ES5+errata: " + e);
assertEq(data7, "data7");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data7");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, false);
assertEq(desc.writable, true);
assertEq(desc.value, "data7");
}
Object.defineProperty(this, "data8",
{
configurable: false,
enumerable: false,
writable: false,
value: "data8"
});
outer = undefined;
try
{
evaluate("function data8() { return 'data8 function'; } outer = data8;");
throw new Error("should have thrown trying to redefine global function " +
"over a non-configurable, non-enumerable, non-writable data" +
"property");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"global function definition, when that function would overwrite " +
"a non-configurable, non-enumerable, non-writable data property, " +
"must throw a TypeError per ES5+errata: " + e);
assertEq(data8, "data8");
assertEq(outer, undefined);
desc = Object.getOwnPropertyDescriptor(this, "data8");
assertEq(desc.configurable, false);
assertEq(desc.enumerable, false);
assertEq(desc.writable, false);
assertEq(desc.value, "data8");
}
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

View File

@ -0,0 +1,124 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 497869;
var summary = "Implement FutureReservedWords per-spec";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var futureReservedWords =
[
"class",
// "const", // Mozilla extension enabled even for versionless code
"enum",
"export",
"extends",
"import",
"super",
];
var strictFutureReservedWords =
[
"implements",
"interface",
"let", // enabled: this file doesn't execute as JS1.7
"package",
"private",
"protected",
"public",
"static",
"yield", // enabled: this file doesn't execute as JS1.7
];
function testWord(word, expectNormal, expectStrict)
{
var actual, status;
// USE IN VARIABLE DECLARATION
actual = "";
status = summary + ", normal var: " + word;
try
{
eval("var " + word + ";");
actual = "no error";
}
catch (e)
{
actual = "error";
status += ", " + e.name + ": " + e.message + " ";
}
reportCompare(expectNormal, actual, status);
actual = "";
status = summary + ", strict var: " + word;
try
{
eval("'use strict'; var " + word + ";");
actual = "no error";
}
catch (e)
{
actual = "error";
status += ", " + e.name + ": " + e.message + " ";
}
reportCompare(expectStrict, actual, status);
// USE AS LHS FOR ASSIGNMENT
actual = "";
status = summary + ", normal assignment: " + word;
try
{
eval(word + " = 'foo';");
actual = "no error";
}
catch(e)
{
actual = "error";
status += ", " + e.name + ": " + e.message + " ";
}
reportCompare(expectNormal, actual, status);
actual = "";
status = summary + ", strict assignment: " + word;
try
{
eval("'use strict'; " + word + " = 'foo';");
actual = "no error";
}
catch(e)
{
actual = "error";
status += ", " + e.name + ": " + e.message + " ";
}
reportCompare(expectStrict, actual, status);
}
function testFutureReservedWord(word)
{
testWord(word, "error", "error");
}
function testStrictFutureReservedWord(word)
{
testWord(word, "no error", "error");
}
futureReservedWords.forEach(testFutureReservedWord);
strictFutureReservedWords.forEach(testStrictFutureReservedWord);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

View File

@ -4,3 +4,6 @@ script redeclare-var-non-writable-property.js
script enumerate-undefined.js
script unwrapped-no-such-method.js
script explicit-undefined-optional-argument.js
script function-definition-eval.js
skip-if(!xulRuntime.shell) script function-definition-evaluate.js # needs evaluate()
script future-reserved-words.js

View File

@ -60,7 +60,6 @@ script regress-233483.js
script regress-234389.js
script regress-238881.js
script regress-238945.js
script regress-240317.js
script regress-240577.js
script regress-243174.js
script regress-243389-n.js

View File

@ -1,68 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor: Bob Clary
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 240317;
var summary = 'Using Reserved identifiers warns';
var actual = '';
var expect = 'no error';
printBugNumber(BUGNUMBER);
printStatus (summary);
function testvar(words)
{
var e;
expect = 'no error';
for (var i = 0; i < words.length; i++)
{
var word = words[i];
actual = '';
status = summary + ': ' + word;
try
{
eval('var ' + word + ';');
actual = 'no error';
}
catch(e)
{
actual = 'error';
status += ', ' + e.name + ': ' + e.message + ' ';
}
reportCompare(expect, actual, status);
actual = '';
status = summary + ': ' + word;
try
{
eval(word + ' = "foo";');
actual = 'no error';
}
catch(e)
{
actual = 'error';
status += ', ' + e.name + ': ' + e.message + ' ';
}
reportCompare(expect, actual, status);
}
}
// future reserved words
var reserved =
['abstract', 'enum', 'int', 'short', 'boolean',
'interface', 'static', 'byte', 'extends',
'long', 'super', 'char', 'final', 'native',
'synchronized', 'class', 'float', 'package', 'throws',
'goto', 'private', 'transient',
'implements', 'protected', 'volatile', 'double',
'public'];
testvar(reserved);

View File

@ -151,7 +151,7 @@ script regress-390597.js
script regress-390598.js
script regress-394967.js
script regress-396326.js
script regress-406572.js
skip script regress-406572.js
script regress-407019.js
script regress-407501.js
skip-if(!xulRuntime.shell) script regress-407720.js # slow

View File

@ -52,13 +52,13 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
f = function() { [super] = q; };
expect = 'function() { [super] = q; }';
f = function() { [implements] = q; };
expect = 'function() { [implements] = q; }';
actual = f + '';
compareSource(expect, actual, summary + ': 1');
f = function() { return { get super() { } } };
expect = 'function() { return { get super() { } }; }';
f = function() { return { get implements() { } } };
expect = 'function() { return { get implements() { } }; }';
actual = f + '';
compareSource(expect, actual, summary + ': 2');

View File

@ -244,6 +244,8 @@ xpc::CompartmentPrivate::~CompartmentPrivate()
{
if (waiverWrapperMap)
delete waiverWrapperMap;
if (expandoMap)
delete expandoMap;
}
static JSBool
@ -402,6 +404,24 @@ struct ClearedGlobalObject : public JSDHashEntryHdr
JSObject* mGlobalObject;
};
static PLDHashOperator
TraceExpandos(XPCWrappedNative *wn, JSObject *expando, void *aClosure)
{
JS_CALL_OBJECT_TRACER(static_cast<JSTracer *>(aClosure), expando, "expando object");
return PL_DHASH_NEXT;
}
static PLDHashOperator
TraceCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClosure)
{
xpc::CompartmentPrivate *priv = (xpc::CompartmentPrivate *)
JS_GetCompartmentPrivate(static_cast<JSTracer *>(aClosure)->context, compartment);
if (priv->expandoMap)
priv->expandoMap->EnumerateRead(TraceExpandos, (JSContext *)aClosure);
return PL_DHASH_NEXT;
}
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc)
{
JSContext *iter = nsnull, *acx;
@ -423,6 +443,10 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc)
if(mJSHolders.ops)
JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc);
// Trace compartments.
GetCompartmentMap().EnumerateRead((XPCCompartmentMap::EnumReadFunction)
TraceCompartment, trc);
}
struct Closure
@ -563,6 +587,15 @@ SweepWaiverWrappers(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT;
}
static PLDHashOperator
SweepExpandos(XPCWrappedNative *wn, JSObject *&expando, void *arg)
{
JSContext *cx = (JSContext *)arg;
return IsAboutToBeFinalized(cx, wn->GetFlatJSObjectNoMark())
? PL_DHASH_REMOVE
: PL_DHASH_NEXT;
}
static PLDHashOperator
SweepCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClosure)
{
@ -570,6 +603,8 @@ SweepCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClos
JS_GetCompartmentPrivate((JSContext *)aClosure, compartment);
if (priv->waiverWrapperMap)
priv->waiverWrapperMap->Enumerate(SweepWaiverWrappers, (JSContext *)aClosure);
if (priv->expandoMap)
priv->expandoMap->Enumerate(SweepExpandos, (JSContext *)aClosure);
return PL_DHASH_NEXT;
}

View File

@ -4449,48 +4449,67 @@ namespace xpc {
struct CompartmentPrivate
{
CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays, bool cycleCollectionEnabled)
: key(key),
ptr(nsnull),
wantXrays(wantXrays),
cycleCollectionEnabled(cycleCollectionEnabled),
waiverWrapperMap(nsnull)
{
}
CompartmentPrivate(PtrAndPrincipalHashKey *key, bool wantXrays, bool cycleCollectionEnabled)
: key(key),
ptr(nsnull),
wantXrays(wantXrays),
cycleCollectionEnabled(cycleCollectionEnabled),
waiverWrapperMap(nsnull),
expandoMap(nsnull)
{
}
CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled)
: key(nsnull),
ptr(ptr),
wantXrays(wantXrays),
cycleCollectionEnabled(cycleCollectionEnabled),
waiverWrapperMap(nsnull)
{
}
CompartmentPrivate(nsISupports *ptr, bool wantXrays, bool cycleCollectionEnabled)
: key(nsnull),
ptr(ptr),
wantXrays(wantXrays),
cycleCollectionEnabled(cycleCollectionEnabled),
waiverWrapperMap(nsnull),
expandoMap(nsnull)
{
}
~CompartmentPrivate();
~CompartmentPrivate();
// NB: key and ptr are mutually exclusive.
nsAutoPtr<PtrAndPrincipalHashKey> key;
nsCOMPtr<nsISupports> ptr;
bool wantXrays;
bool cycleCollectionEnabled;
JSObject2JSObjectMap *waiverWrapperMap;
// NB: key and ptr are mutually exclusive.
nsAutoPtr<PtrAndPrincipalHashKey> key;
nsCOMPtr<nsISupports> ptr;
bool wantXrays;
bool cycleCollectionEnabled;
JSObject2JSObjectMap *waiverWrapperMap;
// NB: we don't want this map to hold a strong reference to the wrapper.
nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
if (!expandoMap) {
expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
if (!expandoMap->Init(8))
return false;
}
return expandoMap->Put(wn, expando);
}
JSObject *LookupExpandoObject(XPCWrappedNative *wn) {
if (!expandoMap)
return nsnull;
return expandoMap->Get(wn);
}
};
inline bool
CompartmentParticipatesInCycleCollection(JSContext *cx, JSCompartment *compartment)
{
CompartmentPrivate *priv =
static_cast<CompartmentPrivate *>(JS_GetCompartmentPrivate(cx, compartment));
NS_ASSERTION(priv, "This should never be null!");
CompartmentPrivate *priv =
static_cast<CompartmentPrivate *>(JS_GetCompartmentPrivate(cx, compartment));
NS_ASSERTION(priv, "This should never be null!");
return priv->cycleCollectionEnabled;
return priv->cycleCollectionEnabled;
}
inline bool
ParticipatesInCycleCollection(JSContext *cx, js::gc::Cell *cell)
{
return CompartmentParticipatesInCycleCollection(cx, cell->compartment());
return CompartmentParticipatesInCycleCollection(cx, cell->compartment());
}
}

View File

@ -139,15 +139,39 @@ GetWrappedNativeObjectFromHolder(JSContext *cx, JSObject *holder)
}
static JSObject *
GetExpandoObject(JSContext *cx, JSObject *holder)
GetExpandoObject(JSObject *holder)
{
JSObject *expando = holder->getSlot(JSSLOT_EXPANDO).toObjectOrNull();
NS_ASSERTION(holder->getJSClass() == &HolderClass, "expected a native property holder object");
return holder->getSlot(JSSLOT_EXPANDO).toObjectOrNull();
}
static JSObject *
EnsureExpandoObject(JSContext *cx, JSObject *holder)
{
NS_ASSERTION(holder->getJSClass() == &HolderClass, "expected a native property holder object");
JSObject *expando = GetExpandoObject(holder);
if (expando)
return expando;
CompartmentPrivate *priv =
(CompartmentPrivate *)JS_GetCompartmentPrivate(cx, holder->compartment());
XPCWrappedNative *wn = GetWrappedNative(GetWrappedNativeObjectFromHolder(cx, holder));
expando = priv->LookupExpandoObject(wn);
if (!expando) {
expando = JS_NewObjectWithGivenProto(cx, nsnull, nsnull, holder->getParent());
expando = JS_NewObjectWithGivenProto(cx, nsnull, nsnull, holder->getParent());
if (!expando)
return NULL;
holder->setSlot(JSSLOT_EXPANDO, ObjectValue(*expando));
// Add the expando object to the expando map to keep it alive.
if (!priv->RegisterExpandoObject(wn, expando)) {
JS_ReportOutOfMemory(cx);
return NULL;
}
// Make sure the wn stays alive so it keeps the expando object alive.
nsRefPtr<nsXPCClassInfo> ci;
CallQueryInterface(wn->Native(), getter_AddRefs(ci));
if (ci)
ci->PreserveWrapper(wn->Native());
}
holder->setSlot(JSSLOT_EXPANDO, ObjectValue(*expando));
return expando;
}
@ -425,19 +449,18 @@ XrayWrapper<Base, Policy>::resolveOwnProperty(JSContext *cx, JSObject *wrapper,
}
JSObject *holder = GetHolder(wrapper);
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
JSObject *expando = GetExpandoObject(holder);
if (expando) {
if (!JS_GetPropertyDescriptorById(cx, expando, id,
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
desc)) {
return false;
}
if (!JS_GetPropertyDescriptorById(cx, expando, id,
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
desc)) {
return false;
if (desc->obj)
return true;
}
if (desc->obj)
return true;
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
@ -627,7 +650,7 @@ XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid
jsdesc->attrs);
}
JSObject *expando = GetExpandoObject(cx, holder);
JSObject *expando = EnsureExpandoObject(cx, holder);
if (!expando)
return false;
@ -657,11 +680,8 @@ EnumerateNames(JSContext *cx, JSObject *wrapper, uintN flags, js::AutoIdVector &
}
// Enumerate expando properties first.
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
if (!js::GetPropertyNames(cx, expando, flags, &props))
JSObject *expando = GetExpandoObject(holder);
if (expando && !js::GetPropertyNames(cx, expando, flags, &props))
return false;
// Force all native properties to be materialized onto the wrapped native.
@ -716,12 +736,14 @@ XrayWrapper<Base, Policy>::delete_(JSContext *cx, JSObject *wrapper, jsid id, bo
return true;
}
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
JSObject *expando = GetExpandoObject(holder);
b = true;
if (expando &&
(!JS_DeletePropertyById2(cx, expando, id, &v) ||
!JS_ValueToBoolean(cx, v, &b))) {
return false;
}
if (!JS_DeletePropertyById2(cx, expando, id, &v) || !JS_ValueToBoolean(cx, v, &b))
return false;
*bp = !!b;
return true;
}
@ -803,11 +825,18 @@ XrayWrapper<Base, Policy>::createHolder(JSContext *cx, JSObject *wrappedNative,
if (!holder)
return nsnull;
CompartmentPrivate *priv =
(CompartmentPrivate *)JS_GetCompartmentPrivate(cx, holder->compartment());
JSObject *inner = wrappedNative;
OBJ_TO_INNER_OBJECT(cx, inner);
XPCWrappedNative *wn = GetWrappedNative(inner);
Value expando = ObjectOrNullValue(priv->LookupExpandoObject(wn));
JS_ASSERT(IS_WN_WRAPPER(wrappedNative) ||
wrappedNative->getClass()->ext.innerObject);
holder->setSlot(JSSLOT_WN_OBJ, ObjectValue(*wrappedNative));
holder->setSlot(JSSLOT_RESOLVING, PrivateValue(NULL));
holder->setSlot(JSSLOT_EXPANDO, NullValue());
holder->setSlot(JSSLOT_EXPANDO, expando);
return holder;
}

View File

@ -21,8 +21,8 @@
<script type="application/javascript">
<![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function runTests() {

View File

@ -22,8 +22,8 @@
<script type="application/javascript">
<![CDATA[
var imports = [ "SimpleTest", "is", "isnot", "ok", "todo" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
var plugin;

View File

@ -18,8 +18,8 @@
SimpleTest.waitForExplicitFinish();
var imports = [ "SimpleTest", "is", "isnot", "ok" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function snapshot(win) {

View File

@ -9,7 +9,7 @@ var ua = navigator.userAgent;
if (/Windows/.test(ua)) {
id = "win";
if (/NT 5\.1/.test(ua) || /NT 5\.2; Win64/.test(ua))
var class = "winxp";
var classname = "winxp";
}
else if (/Linux/.test(ua))
id = "linux";
@ -24,5 +24,5 @@ else
document.documentElement.appendChild(
document.createTextNode("Unrecognized platform")
);
if (class)
document.documentElement.setAttribute("class", class);
if (classname)
document.documentElement.setAttribute("class", classname);

View File

@ -36,8 +36,8 @@
<script type="application/javascript">
var imports = [ "SimpleTest", "is", "isnot", "ok" ];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
var div = document.getElementById("display");

View File

@ -204,8 +204,8 @@
}
var path = _entityEncode(this.path);
var html = this.results.map(function (t) {
var class = t.info ? "info" : "result " + (t.pass ? "passed" : "failed");
return "<p class=\"" + class + "\">" + t.result + " | " + path +
var classname = t.info ? "info" : "result " + (t.pass ? "passed" : "failed");
return "<p class=\"" + classname + "\">" + t.result + " | " + path +
" | " + _entityEncode(t.msg) + "</p>";
}).join("\n");
if (this.duration) {

View File

@ -82,12 +82,12 @@ function do_check_throws(f, type, stack)
do_throw("expected " + type.name + " exception, none thrown", stack);
}
function do_check_class(obj, class, stack)
function do_check_class(obj, classname, stack)
{
if (!stack)
stack = Components.stack.caller;
do_check_eq(Object.prototype.toString.call(obj), "[object " + class + "]", stack);
do_check_eq(Object.prototype.toString.call(obj), "[object " + classname + "]", stack);
}
function run_test()

View File

@ -55,8 +55,8 @@
var gBrowser;
var imports = ["SimpleTest", "ok"];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function finish() {

View File

@ -55,8 +55,8 @@
var gBrowser;
var imports = ["SimpleTest", "ok"];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function finish() {

View File

@ -57,8 +57,8 @@
var gBrowser;
var imports = ["SimpleTest", "ok", "snapshotWindow", "compareSnapshots"];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}
function finish() {

View File

@ -62,8 +62,8 @@
}
var imports = [ "SimpleTest", "ok"];
for each (var import in imports) {
window[import] = window.opener.wrappedJSObject[import];
for each (var name in imports) {
window[name] = window.opener.wrappedJSObject[name];
}