зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central and tracemonkey. (a=blockers)
This commit is contained in:
Коммит
f834b150eb
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
|
@ -0,0 +1,2 @@
|
|||
for (var j=0; j<HOTLOOP; ++j)
|
||||
({'0': 0});
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -5398,7 +5398,7 @@ BEGIN_CASE(JSOP_DEFFUN)
|
|||
*/
|
||||
obj2 = ®s.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 = ®s.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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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, ' ');
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
|
@ -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 +"";
|
||||
}
|
||||
|
|
|
@ -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!");
|
|
@ -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!");
|
|
@ -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!");
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче