зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1054756, part 1 - Support symbol-keyed properties in JSXrayTraits::resolveOwnProperty(). r=jandem.
--HG-- extra : commitid : Iw7k8V0s8vH extra : rebase_source : 47344f609f8282df5cfe30ccb89792e3b26e5d3c
This commit is contained in:
Родитель
15a26cce97
Коммит
cba3fb8913
181
js/src/jsapi.cpp
181
js/src/jsapi.cpp
|
@ -3315,22 +3315,6 @@ JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
|
||||||
: NewNativeFunction(cx, native, nargs, atom);
|
: NewNativeFunction(cx, native, nargs, atom);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSFunction*)
|
|
||||||
JS_NewFunctionById(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
|
|
||||||
HandleId id)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(JSID_IS_STRING(id));
|
|
||||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
|
||||||
MOZ_ASSERT(native);
|
|
||||||
AssertHeapIsIdle(cx);
|
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
|
|
||||||
RootedAtom name(cx, JSID_TO_ATOM(id));
|
|
||||||
return (flags & JSFUN_CONSTRUCTOR)
|
|
||||||
? NewNativeConstructor(cx, native, nargs, name)
|
|
||||||
: NewNativeFunction(cx, native, nargs, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSFunction*)
|
JS_PUBLIC_API(JSFunction*)
|
||||||
JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
|
JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
|
||||||
{
|
{
|
||||||
|
@ -3352,6 +3336,52 @@ JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id
|
||||||
return &funVal.toObject().as<JSFunction>();
|
return &funVal.toObject().as<JSFunction>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JSFunction*)
|
||||||
|
JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id)
|
||||||
|
{
|
||||||
|
// Delay cloning self-hosted functions until they are called. This is
|
||||||
|
// achieved by passing DefineFunction a nullptr JSNative which produces an
|
||||||
|
// interpreted JSFunction where !hasScript. Interpreted call paths then
|
||||||
|
// call InitializeLazyFunctionScript if !hasScript.
|
||||||
|
if (fs->selfHostedName) {
|
||||||
|
MOZ_ASSERT(!fs->call.op);
|
||||||
|
MOZ_ASSERT(!fs->call.info);
|
||||||
|
|
||||||
|
JSAtom* shAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
|
||||||
|
if (!shAtom)
|
||||||
|
return nullptr;
|
||||||
|
RootedPropertyName shName(cx, shAtom->asPropertyName());
|
||||||
|
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||||
|
if (!name)
|
||||||
|
return nullptr;
|
||||||
|
RootedValue funVal(cx);
|
||||||
|
if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs,
|
||||||
|
&funVal))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &funVal.toObject().as<JSFunction>();
|
||||||
|
}
|
||||||
|
|
||||||
|
RootedAtom atom(cx, IdToFunctionName(cx, id));
|
||||||
|
if (!atom)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JSFunction* fun;
|
||||||
|
if (!fs->call.op)
|
||||||
|
fun = NewScriptedFunction(cx, fs->nargs, JSFunction::INTERPRETED_LAZY, atom);
|
||||||
|
else if (fs->flags & JSFUN_CONSTRUCTOR)
|
||||||
|
fun = NewNativeConstructor(cx, fs->call.op, fs->nargs, atom);
|
||||||
|
else
|
||||||
|
fun = NewNativeFunction(cx, fs->call.op, fs->nargs, atom);
|
||||||
|
if (!fun)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (fs->call.info)
|
||||||
|
fun->setJitInfo(fs->call.info);
|
||||||
|
return fun;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||||
MutableHandleObject dynamicScopeObj,
|
MutableHandleObject dynamicScopeObj,
|
||||||
|
@ -3576,6 +3606,59 @@ GenericNativeMethodDispatcher(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return fs->call.op(cx, argc, vp);
|
return fs->call.op(cx, argc, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
DefineFunctionFromSpec(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs, unsigned flags)
|
||||||
|
{
|
||||||
|
GetterOp gop;
|
||||||
|
SetterOp sop;
|
||||||
|
if (flags & JSFUN_STUB_GSOPS) {
|
||||||
|
// JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
|
||||||
|
// the defined property's attributes.
|
||||||
|
flags &= ~JSFUN_STUB_GSOPS;
|
||||||
|
gop = nullptr;
|
||||||
|
sop = nullptr;
|
||||||
|
} else {
|
||||||
|
gop = obj->getClass()->getProperty;
|
||||||
|
sop = obj->getClass()->setProperty;
|
||||||
|
MOZ_ASSERT(gop != JS_PropertyStub);
|
||||||
|
MOZ_ASSERT(sop != JS_StrictPropertyStub);
|
||||||
|
}
|
||||||
|
|
||||||
|
RootedId id(cx);
|
||||||
|
if (!PropertySpecNameToId(cx, fs->name, &id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Define a generic arity N+1 static method for the arity N prototype
|
||||||
|
// method if flags contains JSFUN_GENERIC_NATIVE.
|
||||||
|
if (flags & JSFUN_GENERIC_NATIVE) {
|
||||||
|
// We require that any consumers using JSFUN_GENERIC_NATIVE stash
|
||||||
|
// the prototype and constructor in the global slots before invoking
|
||||||
|
// JS_DefineFunctions on the proto.
|
||||||
|
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
|
||||||
|
MOZ_ASSERT(obj == &obj->global().getPrototype(key).toObject());
|
||||||
|
RootedObject ctor(cx, &obj->global().getConstructor(key).toObject());
|
||||||
|
|
||||||
|
flags &= ~JSFUN_GENERIC_NATIVE;
|
||||||
|
JSFunction* fun = DefineFunction(cx, ctor, id,
|
||||||
|
GenericNativeMethodDispatcher,
|
||||||
|
fs->nargs + 1, flags,
|
||||||
|
gc::AllocKind::FUNCTION_EXTENDED);
|
||||||
|
if (!fun)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// As jsapi.h notes, fs must point to storage that lives as long
|
||||||
|
// as fun->object lives.
|
||||||
|
fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSFunction* fun = NewFunctionFromSpec(cx, fs, id);
|
||||||
|
if (!fun)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RootedValue funVal(cx, ObjectValue(*fun));
|
||||||
|
return DefineProperty(cx, obj, id, funVal, gop, sop, flags & ~JSFUN_FLAGS_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
||||||
PropertyDefinitionBehavior behavior)
|
PropertyDefinitionBehavior behavior)
|
||||||
|
@ -3585,11 +3668,7 @@ JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, obj);
|
assertSameCompartment(cx, obj);
|
||||||
|
|
||||||
RootedId id(cx);
|
|
||||||
for (; fs->name; fs++) {
|
for (; fs->name; fs++) {
|
||||||
if (!PropertySpecNameToId(cx, fs->name, &id))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned flags = fs->flags;
|
unsigned flags = fs->flags;
|
||||||
switch (behavior) {
|
switch (behavior) {
|
||||||
case DefineAllProperties:
|
case DefineAllProperties:
|
||||||
|
@ -3603,67 +3682,9 @@ JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
||||||
if (flags & JSPROP_DEFINE_LATE)
|
if (flags & JSPROP_DEFINE_LATE)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
flags &= ~JSPROP_DEFINE_LATE;
|
|
||||||
|
|
||||||
/*
|
if (!DefineFunctionFromSpec(cx, obj, fs, flags & ~JSPROP_DEFINE_LATE))
|
||||||
* Define a generic arity N+1 static method for the arity N prototype
|
return false;
|
||||||
* method if flags contains JSFUN_GENERIC_NATIVE.
|
|
||||||
*/
|
|
||||||
if (flags & JSFUN_GENERIC_NATIVE) {
|
|
||||||
// We require that any consumers using JSFUN_GENERIC_NATIVE stash
|
|
||||||
// the prototype and constructor in the global slots before invoking
|
|
||||||
// JS_DefineFunctions on the proto.
|
|
||||||
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
|
|
||||||
MOZ_ASSERT(obj == &obj->global().getPrototype(key).toObject());
|
|
||||||
RootedObject ctor(cx, &obj->global().getConstructor(key).toObject());
|
|
||||||
|
|
||||||
flags &= ~JSFUN_GENERIC_NATIVE;
|
|
||||||
JSFunction* fun = DefineFunction(cx, ctor, id,
|
|
||||||
GenericNativeMethodDispatcher,
|
|
||||||
fs->nargs + 1, flags,
|
|
||||||
gc::AllocKind::FUNCTION_EXTENDED);
|
|
||||||
if (!fun)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* As jsapi.h notes, fs must point to storage that lives as long
|
|
||||||
* as fun->object lives.
|
|
||||||
*/
|
|
||||||
fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delay cloning self-hosted functions until they are called. This is
|
|
||||||
* achieved by passing DefineFunction a nullptr JSNative which
|
|
||||||
* produces an interpreted JSFunction where !hasScript. Interpreted
|
|
||||||
* call paths then call InitializeLazyFunctionScript if !hasScript.
|
|
||||||
*/
|
|
||||||
if (fs->selfHostedName) {
|
|
||||||
MOZ_ASSERT(!fs->call.op);
|
|
||||||
MOZ_ASSERT(!fs->call.info);
|
|
||||||
|
|
||||||
JSAtom* shAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
|
|
||||||
if (!shAtom)
|
|
||||||
return false;
|
|
||||||
RootedPropertyName shName(cx, shAtom->asPropertyName());
|
|
||||||
RootedAtom name(cx, IdToFunctionName(cx, id));
|
|
||||||
if (!name)
|
|
||||||
return false;
|
|
||||||
RootedValue funVal(cx);
|
|
||||||
if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs,
|
|
||||||
&funVal))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!DefineProperty(cx, obj, id, funVal, nullptr, nullptr, flags))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
JSFunction* fun = DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
|
|
||||||
if (!fun)
|
|
||||||
return false;
|
|
||||||
if (fs->call.info)
|
|
||||||
fun->setJitInfo(fs->call.info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3124,20 +3124,23 @@ extern JS_PUBLIC_API(JSFunction*)
|
||||||
JS_NewFunction(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
|
JS_NewFunction(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
|
||||||
const char* name);
|
const char* name);
|
||||||
|
|
||||||
/*
|
|
||||||
* Create the function with the name given by the id. JSID_IS_STRING(id) must
|
|
||||||
* be true.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(JSFunction*)
|
|
||||||
JS_NewFunctionById(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
|
|
||||||
JS::Handle<jsid> id);
|
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSFunction*)
|
extern JS_PUBLIC_API(JSFunction*)
|
||||||
GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, JS::Handle<jsid> id,
|
GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id,
|
||||||
unsigned nargs);
|
unsigned nargs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new function based on the given JSFunctionSpec, *fs.
|
||||||
|
* id is the result of a successful call to
|
||||||
|
* `PropertySpecNameToPermanentId(cx, fs->name, &id)`.
|
||||||
|
*
|
||||||
|
* Unlike JS_DefineFunctions, this does not treat fs as an array.
|
||||||
|
* *fs must not be JS_FS_END.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(JSFunction*)
|
||||||
|
NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id);
|
||||||
|
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSObject*)
|
extern JS_PUBLIC_API(JSObject*)
|
||||||
|
|
|
@ -2223,8 +2223,7 @@ js::IdToFunctionName(JSContext* cx, HandleId id)
|
||||||
|
|
||||||
JSFunction*
|
JSFunction*
|
||||||
js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
|
js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
|
||||||
unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */,
|
unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */)
|
||||||
NewObjectKind newKind /* = GenericObject */)
|
|
||||||
{
|
{
|
||||||
GetterOp gop;
|
GetterOp gop;
|
||||||
SetterOp sop;
|
SetterOp sop;
|
||||||
|
@ -2253,11 +2252,11 @@ js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
|
||||||
if (!native)
|
if (!native)
|
||||||
fun = NewScriptedFunction(cx, nargs,
|
fun = NewScriptedFunction(cx, nargs,
|
||||||
JSFunction::INTERPRETED_LAZY, atom,
|
JSFunction::INTERPRETED_LAZY, atom,
|
||||||
allocKind, newKind, obj);
|
allocKind, GenericObject, obj);
|
||||||
else if (flags & JSFUN_CONSTRUCTOR)
|
else if (flags & JSFUN_CONSTRUCTOR)
|
||||||
fun = NewNativeConstructor(cx, native, nargs, atom, allocKind, newKind);
|
fun = NewNativeConstructor(cx, native, nargs, atom, allocKind);
|
||||||
else
|
else
|
||||||
fun = NewNativeFunction(cx, native, nargs, atom, allocKind, newKind);
|
fun = NewNativeFunction(cx, native, nargs, atom, allocKind);
|
||||||
|
|
||||||
if (!fun)
|
if (!fun)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -636,8 +636,7 @@ IdToFunctionName(JSContext* cx, HandleId id);
|
||||||
extern JSFunction*
|
extern JSFunction*
|
||||||
DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,
|
DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,
|
||||||
unsigned nargs, unsigned flags,
|
unsigned nargs, unsigned flags,
|
||||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
gc::AllocKind allocKind = gc::AllocKind::FUNCTION);
|
||||||
NewObjectKind newKind = GenericObject);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
FunctionHasResolveHook(const JSAtomState& atomState, jsid id);
|
FunctionHasResolveHook(const JSAtomState& atomState, jsid id);
|
||||||
|
|
|
@ -518,12 +518,7 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
|
||||||
}
|
}
|
||||||
if (fsMatch) {
|
if (fsMatch) {
|
||||||
// Generate an Xrayed version of the method.
|
// Generate an Xrayed version of the method.
|
||||||
RootedFunction fun(cx);
|
RootedFunction fun(cx, JS::NewFunctionFromSpec(cx, fsMatch, id));
|
||||||
if (fsMatch->selfHostedName) {
|
|
||||||
fun = JS::GetSelfHostedFunction(cx, fsMatch->selfHostedName, id, fsMatch->nargs);
|
|
||||||
} else {
|
|
||||||
fun = JS_NewFunctionById(cx, fsMatch->call.op, fsMatch->nargs, 0, id);
|
|
||||||
}
|
|
||||||
if (!fun)
|
if (!fun)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче