зеркало из 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);
|
||||
}
|
||||
|
||||
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::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>();
|
||||
}
|
||||
|
||||
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
|
||||
CreateNonSyntacticScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
||||
MutableHandleObject dynamicScopeObj,
|
||||
|
@ -3576,6 +3606,59 @@ GenericNativeMethodDispatcher(JSContext* cx, unsigned argc, Value* 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_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
||||
PropertyDefinitionBehavior behavior)
|
||||
|
@ -3585,11 +3668,7 @@ JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
|||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
RootedId id(cx);
|
||||
for (; fs->name; fs++) {
|
||||
if (!PropertySpecNameToId(cx, fs->name, &id))
|
||||
return false;
|
||||
|
||||
unsigned flags = fs->flags;
|
||||
switch (behavior) {
|
||||
case DefineAllProperties:
|
||||
|
@ -3603,67 +3682,9 @@ JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
|
|||
if (flags & JSPROP_DEFINE_LATE)
|
||||
continue;
|
||||
}
|
||||
flags &= ~JSPROP_DEFINE_LATE;
|
||||
|
||||
/*
|
||||
* 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)));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
if (!DefineFunctionFromSpec(cx, obj, fs, flags & ~JSPROP_DEFINE_LATE))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3124,20 +3124,23 @@ extern JS_PUBLIC_API(JSFunction*)
|
|||
JS_NewFunction(JSContext* cx, JSNative call, unsigned nargs, unsigned flags,
|
||||
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 {
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
|
|
|
@ -2223,8 +2223,7 @@ js::IdToFunctionName(JSContext* cx, HandleId id)
|
|||
|
||||
JSFunction*
|
||||
js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
|
||||
unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */)
|
||||
{
|
||||
GetterOp gop;
|
||||
SetterOp sop;
|
||||
|
@ -2253,11 +2252,11 @@ js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
|
|||
if (!native)
|
||||
fun = NewScriptedFunction(cx, nargs,
|
||||
JSFunction::INTERPRETED_LAZY, atom,
|
||||
allocKind, newKind, obj);
|
||||
allocKind, GenericObject, obj);
|
||||
else if (flags & JSFUN_CONSTRUCTOR)
|
||||
fun = NewNativeConstructor(cx, native, nargs, atom, allocKind, newKind);
|
||||
fun = NewNativeConstructor(cx, native, nargs, atom, allocKind);
|
||||
else
|
||||
fun = NewNativeFunction(cx, native, nargs, atom, allocKind, newKind);
|
||||
fun = NewNativeFunction(cx, native, nargs, atom, allocKind);
|
||||
|
||||
if (!fun)
|
||||
return nullptr;
|
||||
|
|
|
@ -636,8 +636,7 @@ IdToFunctionName(JSContext* cx, HandleId id);
|
|||
extern JSFunction*
|
||||
DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,
|
||||
unsigned nargs, unsigned flags,
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
gc::AllocKind allocKind = gc::AllocKind::FUNCTION);
|
||||
|
||||
bool
|
||||
FunctionHasResolveHook(const JSAtomState& atomState, jsid id);
|
||||
|
|
|
@ -518,12 +518,7 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
|
|||
}
|
||||
if (fsMatch) {
|
||||
// Generate an Xrayed version of the method.
|
||||
RootedFunction fun(cx);
|
||||
if (fsMatch->selfHostedName) {
|
||||
fun = JS::GetSelfHostedFunction(cx, fsMatch->selfHostedName, id, fsMatch->nargs);
|
||||
} else {
|
||||
fun = JS_NewFunctionById(cx, fsMatch->call.op, fsMatch->nargs, 0, id);
|
||||
}
|
||||
RootedFunction fun(cx, JS::NewFunctionFromSpec(cx, fsMatch, id));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче