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:
Jason Orendorff 2015-05-01 14:03:17 -05:00
Родитель b60a45cbf7
Коммит 112cb52d91
29 изменённых файлов: 211 добавлений и 118 удалений

Просмотреть файл

@ -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;
}