зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1140482 - Add JSPROP_RESOLVING. Give NativeDefineProperty standard behavior in cases where a non-resolving define needs to trigger a resolve hook. r=Waldo.
--HG-- extra : rebase_source : c63bb83179ec98e9f93ebb86cb488d65f980a07e
This commit is contained in:
Родитель
b60a45cbf7
Коммит
112cb52d91
|
@ -1152,10 +1152,12 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
|
|||
mData, nullptr, nameSpaceManager, proto,
|
||||
&desc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() &&
|
||||
!JS_DefineUCProperty(cx, global, mData->mNameUTF16,
|
||||
NS_strlen(mData->mNameUTF16), desc)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined()) {
|
||||
desc.attributesRef() |= JSPROP_RESOLVING;
|
||||
if (!JS_DefineUCProperty(cx, global, mData->mNameUTF16,
|
||||
NS_strlen(mData->mNameUTF16), desc)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -550,7 +550,7 @@ DefineConstructor(JSContext* cx, JS::Handle<JSObject*> global, const char* name,
|
|||
|
||||
// This is Enumerable: False per spec.
|
||||
return alreadyDefined ||
|
||||
JS_DefineProperty(cx, global, name, constructor, 0);
|
||||
JS_DefineProperty(cx, global, name, constructor, JSPROP_RESOLVING);
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
|
|
|
@ -7803,9 +7803,11 @@ class CGResolveHook(CGAbstractClassHook):
|
|||
// If desc.value() is undefined, then the DoResolve call
|
||||
// has already defined it on the object. Don't try to also
|
||||
// define it.
|
||||
if (!desc.value().isUndefined() &&
|
||||
!JS_DefinePropertyById(cx, obj, id, desc)) {
|
||||
return false;
|
||||
if (!desc.value().isUndefined()) {
|
||||
desc.attributesRef() |= JSPROP_RESOLVING;
|
||||
if (!JS_DefinePropertyById(cx, obj, id, desc)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*resolvedp = true;
|
||||
return true;
|
||||
|
|
|
@ -1228,8 +1228,11 @@ AtomicsObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
|
|||
RootedValue AtomicsValue(cx, ObjectValue(*Atomics));
|
||||
|
||||
// Everything is set up, install Atomics on the global object.
|
||||
if (!DefineProperty(cx, global, cx->names().Atomics, AtomicsValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, global, cx->names().Atomics, AtomicsValue, nullptr, nullptr,
|
||||
JSPROP_RESOLVING))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
global->setConstructor(JSProto_Atomics, AtomicsValue);
|
||||
return Atomics;
|
||||
|
|
|
@ -2049,8 +2049,11 @@ js::InitIntlClass(JSContext* cx, HandleObject obj)
|
|||
return nullptr;
|
||||
|
||||
RootedValue IntlValue(cx, ObjectValue(*Intl));
|
||||
if (!DefineProperty(cx, global, cx->names().Intl, IntlValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, global, cx->names().Intl, IntlValue, nullptr, nullptr,
|
||||
JSPROP_RESOLVING))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!JS_DefineFunctions(cx, Intl, intl_static_methods))
|
||||
return nullptr;
|
||||
|
|
|
@ -1132,7 +1132,8 @@ FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject pro
|
|||
|
||||
/* ES5 15.1.2.1. */
|
||||
RootedId evalId(cx, NameToId(cx->names().eval));
|
||||
JSObject* evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1, JSFUN_STUB_GSOPS);
|
||||
JSObject* evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1,
|
||||
JSFUN_STUB_GSOPS | JSPROP_RESOLVING);
|
||||
if (!evalobj)
|
||||
return false;
|
||||
self->setOriginalEval(evalobj);
|
||||
|
|
|
@ -475,8 +475,11 @@ SIMDObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
|
|||
|
||||
// Everything is set up, install SIMD on the global object.
|
||||
RootedValue SIMDValue(cx, ObjectValue(*SIMD));
|
||||
if (!DefineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr,
|
||||
JSPROP_RESOLVING))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
global->setConstructor(JSProto_SIMD, SIMDValue);
|
||||
return SIMD;
|
||||
|
|
|
@ -1325,8 +1325,11 @@ GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
|
|||
// Everything is setup, install module on the global object:
|
||||
RootedValue moduleValue(cx, ObjectValue(*module));
|
||||
global->setConstructor(JSProto_TypedObject, moduleValue);
|
||||
if (!DefineProperty(cx, global, cx->names().TypedObject, moduleValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, global, cx->names().TypedObject, moduleValue, nullptr, nullptr,
|
||||
JSPROP_RESOLVING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ document_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* res
|
|||
return false;
|
||||
|
||||
JS::Rooted<JS::Value> allValue(cx, JS::ObjectValue(*docAll));
|
||||
if (!JS_DefinePropertyById(cx, obj, id, allValue, 0))
|
||||
if (!JS_DefinePropertyById(cx, obj, id, allValue, JSPROP_RESOLVING))
|
||||
return false;
|
||||
|
||||
*resolvedp = true;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
* Test that resolve hook recursion for the same object and property is
|
||||
* prevented.
|
||||
*/
|
||||
|
||||
BEGIN_TEST(testResolveRecursion)
|
||||
{
|
||||
static const JSClass my_resolve_class = {
|
||||
|
@ -88,7 +87,7 @@ doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
|||
CHECK_EQUAL(resolveEntryCount, 1);
|
||||
EVAL("obj2.y = true", &v);
|
||||
CHECK_SAME(v, JSVAL_TRUE);
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, 0));
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, JSPROP_RESOLVING));
|
||||
*resolvedp = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
|||
} else if (JS_FlatStringEqualsAscii(str, "y")) {
|
||||
if (obj == obj2) {
|
||||
CHECK_EQUAL(resolveEntryCount, 2);
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JS::NullHandleValue, 0));
|
||||
CHECK(JS_DefinePropertyById(cx, obj, id, JS::NullHandleValue, JSPROP_RESOLVING));
|
||||
EVAL("obj1.x", &v);
|
||||
CHECK(v.isUndefined());
|
||||
EVAL("obj1.y", &v);
|
||||
|
@ -134,5 +133,49 @@ my_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp
|
|||
return static_cast<cls_testResolveRecursion*>(JS_GetPrivate(obj))->
|
||||
doResolve(obj, id, resolvedp);
|
||||
}
|
||||
|
||||
END_TEST(testResolveRecursion)
|
||||
|
||||
/*
|
||||
* Test that JS_InitStandardClasses does not cause resolve hooks to be called.
|
||||
*
|
||||
* (XPConnect apparently does have global classes, such as the one created by
|
||||
* nsMessageManagerScriptExecutor::InitChildGlobalInternal(), that have resolve
|
||||
* hooks which can call back into JS, and on which JS_InitStandardClasses is
|
||||
* called. Calling back into JS in the middle of resolving `undefined` is bad.)
|
||||
*/
|
||||
BEGIN_TEST(testResolveRecursion_InitStandardClasses)
|
||||
{
|
||||
CHECK(JS_InitStandardClasses(cx, global));
|
||||
return true;
|
||||
}
|
||||
|
||||
const JSClass* getGlobalClass() override {
|
||||
static const JSClass myGlobalClass = {
|
||||
"testResolveRecursion_InitStandardClasses_myGlobalClass",
|
||||
JSCLASS_GLOBAL_FLAGS,
|
||||
nullptr, // add
|
||||
nullptr, // delete
|
||||
nullptr, // get
|
||||
nullptr, // set
|
||||
nullptr, // enumerate
|
||||
my_resolve,
|
||||
nullptr, // mayResolve
|
||||
nullptr, // convert
|
||||
nullptr, // finalize
|
||||
nullptr, // call
|
||||
nullptr, // hasInstance
|
||||
nullptr, // construct
|
||||
JS_GlobalObjectTraceHook
|
||||
};
|
||||
|
||||
return &myGlobalClass;
|
||||
}
|
||||
|
||||
static bool
|
||||
my_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("resolve hook should not be called from InitStandardClasses");
|
||||
JS_ReportError(cx, "FAIL");
|
||||
return false;
|
||||
}
|
||||
END_TEST(testResolveRecursion_InitStandardClasses)
|
||||
|
|
|
@ -1231,9 +1231,8 @@ JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* reso
|
|||
JSAtom* undefinedAtom = cx->names().undefined;
|
||||
if (idAtom == undefinedAtom) {
|
||||
*resolved = true;
|
||||
return DefineProperty(cx, obj, undefinedAtom->asPropertyName(),
|
||||
UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING);
|
||||
}
|
||||
|
||||
/* Try for class constructors/prototypes named by well-known atoms. */
|
||||
|
|
|
@ -861,26 +861,6 @@ class MOZ_STACK_CLASS SourceBufferHolder final
|
|||
|
||||
#define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */
|
||||
|
||||
#define JSPROP_REDEFINE_NONCONFIGURABLE 0x800 /* If set, will allow redefining a
|
||||
non-configurable property, but
|
||||
only on a non-DOM global. This
|
||||
is a temporary hack that will
|
||||
need to go away in bug
|
||||
1105518 */
|
||||
|
||||
#define JSPROP_IGNORE_ENUMERATE 0x1000 /* ignore the value in JSPROP_ENUMERATE.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_READONLY 0x2000 /* ignore the value in JSPROP_READONLY.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_PERMANENT 0x4000 /* ignore the value in JSPROP_PERMANENT.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_VALUE 0x8000 /* ignore the Value in the descriptor. Nothing was
|
||||
specified when passed to Object.defineProperty
|
||||
from script. */
|
||||
|
||||
/*
|
||||
* Specify a generic native prototype methods, i.e., methods of a class
|
||||
* prototype that are exposed as static methods taking an extra leading
|
||||
|
@ -895,6 +875,40 @@ class MOZ_STACK_CLASS SourceBufferHolder final
|
|||
|
||||
#define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */
|
||||
|
||||
/*
|
||||
* If set, will allow redefining a non-configurable property, but only on a
|
||||
* non-DOM global. This is a temporary hack that will need to go away in bug
|
||||
* 1105518.
|
||||
*/
|
||||
#define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000
|
||||
|
||||
/*
|
||||
* Resolve hooks and enumerate hooks must pass this flag when calling
|
||||
* JS_Define* APIs to reify lazily-defined properties.
|
||||
*
|
||||
* JSPROP_RESOLVING is used only with property-defining APIs. It tells the
|
||||
* engine to skip the resolve hook when performing the lookup at the beginning
|
||||
* of property definition. This keeps the resolve hook from accidentally
|
||||
* triggering itself: unchecked recursion.
|
||||
*
|
||||
* For enumerate hooks, triggering the resolve hook would be merely silly, not
|
||||
* fatal, except in some cases involving non-configurable properties.
|
||||
*/
|
||||
#define JSPROP_RESOLVING 0x2000
|
||||
|
||||
#define JSPROP_IGNORE_ENUMERATE 0x4000 /* ignore the value in JSPROP_ENUMERATE.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_READONLY 0x8000 /* ignore the value in JSPROP_READONLY.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_PERMANENT 0x10000 /* ignore the value in JSPROP_PERMANENT.
|
||||
This flag only valid when defining over
|
||||
an existing property. */
|
||||
#define JSPROP_IGNORE_VALUE 0x20000 /* ignore the Value in the descriptor. Nothing was
|
||||
specified when passed to Object.defineProperty
|
||||
from script. */
|
||||
|
||||
/*
|
||||
* The first call to JS_CallOnce by any thread in a process will call 'func'.
|
||||
* Later calls to JS_CallOnce with the same JSCallOnceType object will be
|
||||
|
@ -2563,6 +2577,7 @@ class PropertyDescriptorOperations
|
|||
JSPROP_SETTER |
|
||||
JSPROP_SHARED |
|
||||
JSPROP_REDEFINE_NONCONFIGURABLE |
|
||||
JSPROP_RESOLVING |
|
||||
SHADOWABLE)) == 0);
|
||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
|
||||
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
|
||||
|
@ -2581,6 +2596,12 @@ class PropertyDescriptorOperations
|
|||
}
|
||||
MOZ_ASSERT(getter() != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter() != JS_StrictPropertyStub);
|
||||
|
||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE));
|
||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT));
|
||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY));
|
||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE));
|
||||
MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2594,6 +2615,7 @@ class PropertyDescriptorOperations
|
|||
JSPROP_SETTER |
|
||||
JSPROP_SHARED |
|
||||
JSPROP_REDEFINE_NONCONFIGURABLE |
|
||||
JSPROP_RESOLVING |
|
||||
SHADOWABLE)) == 0);
|
||||
MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER));
|
||||
#endif
|
||||
|
|
|
@ -363,32 +363,30 @@ static const JSPropertySpec function_properties[] = {
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
static JSObject*
|
||||
ResolveInterpretedFunctionPrototype(JSContext* cx, HandleObject obj)
|
||||
static bool
|
||||
ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
|
||||
MOZ_ASSERT(!fun->isFunctionPrototype());
|
||||
#endif
|
||||
MOZ_ASSERT(id == NameToId(cx->names().prototype));
|
||||
|
||||
// Assert that fun is not a compiler-created function object, which
|
||||
// must never leak to script or embedding code and then be mutated.
|
||||
// Also assert that obj is not bound, per the ES5 15.3.4.5 ref above.
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(obj));
|
||||
MOZ_ASSERT(!obj->isBoundFunction());
|
||||
// Also assert that fun is not bound, per the ES5 15.3.4.5 ref above.
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(fun));
|
||||
MOZ_ASSERT(!fun->isBoundFunction());
|
||||
|
||||
// Make the prototype object an instance of Object with the same parent as
|
||||
// the function object itself, unless the function is an ES6 generator. In
|
||||
// that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
|
||||
// the GeneratorObjectPrototype singleton.
|
||||
bool isStarGenerator = obj->as<JSFunction>().isStarGenerator();
|
||||
Rooted<GlobalObject*> global(cx, &obj->global());
|
||||
bool isStarGenerator = fun->isStarGenerator();
|
||||
Rooted<GlobalObject*> global(cx, &fun->global());
|
||||
RootedObject objProto(cx);
|
||||
if (isStarGenerator)
|
||||
objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
|
||||
else
|
||||
objProto = obj->global().getOrCreateObjectPrototype(cx);
|
||||
objProto = fun->global().getOrCreateObjectPrototype(cx);
|
||||
if (!objProto)
|
||||
return nullptr;
|
||||
|
||||
|
@ -397,26 +395,21 @@ ResolveInterpretedFunctionPrototype(JSContext* cx, HandleObject obj)
|
|||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
// Per ES5 15.3.5.2 a user-defined function's .prototype property is
|
||||
// initially non-configurable, non-enumerable, and writable.
|
||||
RootedValue protoVal(cx, ObjectValue(*proto));
|
||||
if (!DefineProperty(cx, obj, cx->names().prototype, protoVal, nullptr, nullptr,
|
||||
JSPROP_PERMANENT))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Per ES5 13.2 the prototype's .constructor property is configurable,
|
||||
// non-enumerable, and writable. However, per the 15 July 2013 ES6 draft,
|
||||
// section 15.19.3, the .prototype of a generator function does not link
|
||||
// back with a .constructor.
|
||||
if (!isStarGenerator) {
|
||||
RootedValue objVal(cx, ObjectValue(*obj));
|
||||
RootedValue objVal(cx, ObjectValue(*fun));
|
||||
if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return proto;
|
||||
// Per ES5 15.3.5.2 a user-defined function's .prototype property is
|
||||
// initially non-configurable, non-enumerable, and writable.
|
||||
RootedValue protoVal(cx, ObjectValue(*proto));
|
||||
return DefineProperty(cx, fun, id, protoVal, nullptr, nullptr,
|
||||
JSPROP_PERMANENT | JSPROP_RESOLVING);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -458,7 +451,7 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
if (fun->isBuiltin() || !fun->isConstructor())
|
||||
return true;
|
||||
|
||||
if (!ResolveInterpretedFunctionPrototype(cx, fun))
|
||||
if (!ResolveInterpretedFunctionPrototype(cx, fun, id))
|
||||
return false;
|
||||
|
||||
*resolvedp = true;
|
||||
|
@ -501,8 +494,11 @@ fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
v.setString(fun->atom() == nullptr ? cx->runtime()->emptyString : fun->atom());
|
||||
}
|
||||
|
||||
if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr, JSPROP_READONLY))
|
||||
if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr,
|
||||
JSPROP_READONLY | JSPROP_RESOLVING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isLength)
|
||||
fun->setResolvedLength();
|
||||
|
|
|
@ -1622,8 +1622,11 @@ js::InitMathClass(JSContext* cx, HandleObject obj)
|
|||
if (!Math)
|
||||
return nullptr;
|
||||
|
||||
if (!JS_DefineProperty(cx, obj, js_Math_str, Math, 0, JS_STUBGETTER, JS_STUBSETTER))
|
||||
if (!JS_DefineProperty(cx, obj, js_Math_str, Math, JSPROP_RESOLVING,
|
||||
JS_STUBGETTER, JS_STUBSETTER))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (!JS_DefineFunctions(cx, Math, math_static_methods))
|
||||
return nullptr;
|
||||
if (!JS_DefineConstDoubles(cx, Math, math_constants))
|
||||
|
|
|
@ -457,8 +457,8 @@ js::num_parseInt(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
static const JSFunctionSpec number_functions[] = {
|
||||
JS_SELF_HOSTED_FN(js_isNaN_str, "Global_isNaN", 1,0),
|
||||
JS_SELF_HOSTED_FN(js_isFinite_str, "Global_isFinite", 1,0),
|
||||
JS_SELF_HOSTED_FN(js_isNaN_str, "Global_isNaN", 1, JSPROP_RESOLVING),
|
||||
JS_SELF_HOSTED_FN(js_isFinite_str, "Global_isFinite", 1, JSPROP_RESOLVING),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -1176,20 +1176,22 @@ js::InitNumberClass(JSContext* cx, HandleObject obj)
|
|||
|
||||
/* Number.parseInt should be the same function object as global parseInt. */
|
||||
RootedId parseIntId(cx, NameToId(cx->names().parseInt));
|
||||
JSFunction* parseInt = DefineFunction(cx, global, parseIntId, num_parseInt, 2, 0);
|
||||
if(!parseInt)
|
||||
JSFunction* parseInt = DefineFunction(cx, global, parseIntId, num_parseInt, 2,
|
||||
JSPROP_RESOLVING);
|
||||
if (!parseInt)
|
||||
return nullptr;
|
||||
RootedValue parseIntValue(cx, ObjectValue(*parseInt));
|
||||
if(!DefineProperty(cx, ctor, parseIntId, parseIntValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, ctor, parseIntId, parseIntValue, nullptr, nullptr, 0))
|
||||
return nullptr;
|
||||
|
||||
/* Number.parseFloat should be the same function object as global parseFloat. */
|
||||
RootedId parseFloatId(cx, NameToId(cx->names().parseFloat));
|
||||
JSFunction* parseFloat = DefineFunction(cx, global, parseFloatId, num_parseFloat, 1, 0);
|
||||
if(!parseFloat)
|
||||
JSFunction* parseFloat = DefineFunction(cx, global, parseFloatId, num_parseFloat, 1,
|
||||
JSPROP_RESOLVING);
|
||||
if (!parseFloat)
|
||||
return nullptr;
|
||||
RootedValue parseFloatValue(cx, ObjectValue(*parseFloat));
|
||||
if(!DefineProperty(cx, ctor, parseFloatId, parseFloatValue, nullptr, nullptr, 0))
|
||||
if (!DefineProperty(cx, ctor, parseFloatId, parseFloatValue, nullptr, nullptr, 0))
|
||||
return nullptr;
|
||||
|
||||
RootedValue valueNaN(cx, cx->runtime()->NaNValue);
|
||||
|
@ -1197,9 +1199,9 @@ js::InitNumberClass(JSContext* cx, HandleObject obj)
|
|||
|
||||
/* ES5 15.1.1.1, 15.1.1.2 */
|
||||
if (!NativeDefineProperty(cx, global, cx->names().NaN, valueNaN, nullptr, nullptr,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY) ||
|
||||
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING) ||
|
||||
!NativeDefineProperty(cx, global, cx->names().Infinity, valueInfinity, nullptr, nullptr,
|
||||
JSPROP_PERMANENT | JSPROP_READONLY))
|
||||
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -900,9 +900,11 @@ js::InitJSONClass(JSContext* cx, HandleObject obj)
|
|||
if (!JSON)
|
||||
return nullptr;
|
||||
|
||||
if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, 0,
|
||||
if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, JSPROP_RESOLVING,
|
||||
JS_STUBGETTER, JS_STUBSETTER))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!JS_DefineFunctions(cx, JSON, json_static_methods))
|
||||
return nullptr;
|
||||
|
|
|
@ -362,15 +362,15 @@ str_uneval(JSContext* cx, unsigned argc, Value* vp)
|
|||
#endif
|
||||
|
||||
static const JSFunctionSpec string_functions[] = {
|
||||
JS_FN(js_escape_str, str_escape, 1,0),
|
||||
JS_FN(js_unescape_str, str_unescape, 1,0),
|
||||
JS_FN(js_escape_str, str_escape, 1, JSPROP_RESOLVING),
|
||||
JS_FN(js_unescape_str, str_unescape, 1, JSPROP_RESOLVING),
|
||||
#if JS_HAS_UNEVAL
|
||||
JS_FN(js_uneval_str, str_uneval, 1,0),
|
||||
JS_FN(js_uneval_str, str_uneval, 1, JSPROP_RESOLVING),
|
||||
#endif
|
||||
JS_FN(js_decodeURI_str, str_decodeURI, 1,0),
|
||||
JS_FN(js_encodeURI_str, str_encodeURI, 1,0),
|
||||
JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1,0),
|
||||
JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1,0),
|
||||
JS_FN(js_decodeURI_str, str_decodeURI, 1, JSPROP_RESOLVING),
|
||||
JS_FN(js_encodeURI_str, str_encodeURI, 1, JSPROP_RESOLVING),
|
||||
JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1, JSPROP_RESOLVING),
|
||||
JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1, JSPROP_RESOLVING),
|
||||
|
||||
JS_FS_END
|
||||
};
|
||||
|
@ -387,8 +387,11 @@ str_enumerate(JSContext* cx, HandleObject obj)
|
|||
if (!str1)
|
||||
return false;
|
||||
value.setString(str1);
|
||||
if (!DefineElement(cx, obj, i, value, nullptr, nullptr, STRING_ELEMENT_ATTRS))
|
||||
if (!DefineElement(cx, obj, i, value, nullptr, nullptr,
|
||||
STRING_ELEMENT_ATTRS | JSPROP_RESOLVING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -415,8 +418,11 @@ str_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
if (!str1)
|
||||
return false;
|
||||
RootedValue value(cx, StringValue(str1));
|
||||
if (!DefineElement(cx, obj, uint32_t(slot), value, nullptr, nullptr, STRING_ELEMENT_ATTRS))
|
||||
if (!DefineElement(cx, obj, uint32_t(slot), value, nullptr, nullptr,
|
||||
STRING_ELEMENT_ATTRS | JSPROP_RESOLVING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*resolvedp = true;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -774,10 +774,8 @@ js::InitProxyClass(JSContext* cx, HandleObject obj)
|
|||
|
||||
if (!JS_DefineFunctions(cx, ctor, static_methods))
|
||||
return nullptr;
|
||||
if (!JS_DefineProperty(cx, obj, "Proxy", ctor, 0,
|
||||
JS_STUBGETTER, JS_STUBSETTER)) {
|
||||
if (!JS_DefineProperty(cx, obj, "Proxy", ctor, JSPROP_RESOLVING, JS_STUBGETTER, JS_STUBSETTER))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
global->setConstructor(JSProto_Proxy, ObjectValue(*ctor));
|
||||
return ctor;
|
||||
|
|
|
@ -355,7 +355,7 @@ args_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
{
|
||||
Rooted<NormalArgumentsObject*> argsobj(cx, &obj->as<NormalArgumentsObject>());
|
||||
|
||||
unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
|
||||
unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE | JSPROP_RESOLVING;
|
||||
if (JSID_IS_INT(id)) {
|
||||
uint32_t arg = uint32_t(JSID_TO_INT(id));
|
||||
if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
|
||||
|
@ -490,6 +490,7 @@ strictargs_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp
|
|||
setter = CastAsSetterOp(argsobj->global().getThrowTypeError());
|
||||
}
|
||||
|
||||
attrs |= JSPROP_RESOLVING;
|
||||
if (!NativeDefineProperty(cx, argsobj, id, UndefinedHandleValue, getter, setter, attrs))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -329,7 +329,7 @@ GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global)
|
|||
{
|
||||
/* Define a top-level property 'undefined' with the undefined value. */
|
||||
if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
|
||||
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
|
||||
nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1248,26 +1248,17 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
// distinguish the two cases, we note that when resolving, the
|
||||
// property won't already exist; whereas the first time it is
|
||||
// redefined, it will.
|
||||
if (obj->containsPure(id))
|
||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0)
|
||||
obj->as<ArgumentsObject>().markLengthOverridden();
|
||||
}
|
||||
}
|
||||
|
||||
// 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2.
|
||||
RootedShape shape(cx);
|
||||
if (desc_.hasValue()) {
|
||||
// If we did a normal lookup here, it would cause resolve hook recursion in
|
||||
// the following case. Suppose the first script we run in a lazy global is
|
||||
// |parseInt()|.
|
||||
// - js::InitNumberClass is called to resolve parseInt.
|
||||
// - js::InitNumberClass tries to define the Number constructor on the
|
||||
// global.
|
||||
// - We end up here.
|
||||
// - This lookup for 'Number' triggers the global resolve hook.
|
||||
// - js::InitNumberClass is called again, this time to resolve Number.
|
||||
// - It creates a second Number constructor, which trips an assertion.
|
||||
//
|
||||
// Therefore we do a special lookup that does not call the resolve hook.
|
||||
if (desc_.attributes() & JSPROP_RESOLVING) {
|
||||
// We are being called from a resolve or enumerate hook to reify a
|
||||
// lazily-resolved property. To avoid reentering the resolve hook and
|
||||
// recursing forever, skip the resolve hook when doing this lookup.
|
||||
NativeLookupOwnPropertyNoResolve(cx, obj, id, &shape);
|
||||
} else {
|
||||
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
|
||||
|
|
|
@ -319,7 +319,8 @@ nsXPCComponents_Interfaces::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_READONLY |
|
||||
JSPROP_PERMANENT);
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_RESOLVING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -557,7 +558,8 @@ nsXPCComponents_InterfacesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
JS_DefinePropertyById(cx, obj, id, idobj,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_READONLY |
|
||||
JSPROP_PERMANENT);
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_RESOLVING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,7 +777,8 @@ nsXPCComponents_Classes::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_READONLY |
|
||||
JSPROP_PERMANENT);
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_RESOLVING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1013,7 +1016,8 @@ nsXPCComponents_ClassesByID::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
*_retval = JS_DefinePropertyById(cx, obj, id, idobj,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_READONLY |
|
||||
JSPROP_PERMANENT);
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_RESOLVING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1208,7 +1212,8 @@ nsXPCComponents_Results::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv,
|
||||
JSPROP_ENUMERATE |
|
||||
JSPROP_READONLY |
|
||||
JSPROP_PERMANENT)) {
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_RESOLVING)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,7 +402,7 @@ nsJSIID::Resolve(nsIXPConnectWrappedNative* wrapper,
|
|||
*resolvedp = true;
|
||||
*_retval = JS_DefinePropertyById(cx, obj, id, val,
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY |
|
||||
JSPROP_PERMANENT);
|
||||
JSPROP_PERMANENT | JSPROP_RESOLVING);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -199,6 +199,8 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
|||
bool found;
|
||||
const char* name;
|
||||
|
||||
propFlags |= JSPROP_RESOLVING;
|
||||
|
||||
if (set) {
|
||||
if (iface)
|
||||
found = true;
|
||||
|
@ -364,6 +366,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
|
|||
AutoResolveName arn(ccx, id);
|
||||
if (resolved)
|
||||
*resolved = true;
|
||||
desc.attributesRef() |= JSPROP_RESOLVING;
|
||||
return JS_DefinePropertyById(ccx, obj, id, desc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ XPCWrappedNativeScope::AttachComponentsObject(JSContext* aCx)
|
|||
// The global Components property is non-configurable if it's a full
|
||||
// nsXPCComponents object. That way, if it's an nsXPCComponentsBase,
|
||||
// enableUniversalXPConnect can upgrade it later.
|
||||
unsigned attrs = JSPROP_READONLY;
|
||||
unsigned attrs = JSPROP_READONLY | JSPROP_RESOLVING;
|
||||
nsCOMPtr<nsIXPCComponents> c = do_QueryInterface(mComponents);
|
||||
if (c)
|
||||
attrs |= JSPROP_PERMANENT;
|
||||
|
|
|
@ -106,7 +106,8 @@ AsyncStatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
uint32_t idx = JSID_TO_INT(aId);
|
||||
// All indexes are good because we don't know how many parameters there
|
||||
// really are.
|
||||
ok = ::JS_DefineElement(aCtx, scopeObj, idx, JS::UndefinedHandleValue, 0);
|
||||
ok = ::JS_DefineElement(aCtx, scopeObj, idx, JS::UndefinedHandleValue,
|
||||
JSPROP_RESOLVING);
|
||||
resolved = true;
|
||||
}
|
||||
else if (JSID_IS_STRING(aId)) {
|
||||
|
@ -114,7 +115,8 @@ AsyncStatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
// we must assume that there is. This screws the rest of the prototype
|
||||
// chain, but people really shouldn't be depending on this anyways.
|
||||
JS::Rooted<jsid> id(aCtx, aId);
|
||||
ok = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, 0);
|
||||
ok = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue,
|
||||
JSPROP_RESOLVING);
|
||||
resolved = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ StatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
JS::RootedObject scope(aCtx, aScopeObj);
|
||||
if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) {
|
||||
*_retval = ::JS_DefineFunction(aCtx, scope, "step", stepFunc,
|
||||
0, 0) != nullptr;
|
||||
0, JSPROP_RESOLVING) != nullptr;
|
||||
*aResolvedp = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,8 @@ StatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
if (idx >= mParamCount)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue, JSPROP_ENUMERATE);
|
||||
ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue,
|
||||
JSPROP_ENUMERATE | JSPROP_RESOLVING);
|
||||
resolved = true;
|
||||
}
|
||||
else if (JSID_IS_STRING(id)) {
|
||||
|
@ -165,7 +166,8 @@ StatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
uint32_t idx;
|
||||
nsresult rv = mStatement->GetParameterIndex(name, &idx);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue, JSPROP_ENUMERATE);
|
||||
ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue,
|
||||
JSPROP_ENUMERATE | JSPROP_RESOLVING);
|
||||
resolved = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,8 @@ StatementRow::Resolve(nsIXPConnectWrappedNative *aWrapper,
|
|||
}
|
||||
|
||||
JS::Rooted<jsid> id(aCtx, aId);
|
||||
*_retval = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, 0);
|
||||
*_retval = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue,
|
||||
JSPROP_RESOLVING);
|
||||
*aResolvedp = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче