Clean up API for creating natives with reserved slots, fix uses in CTypes and jsworkers shell, bug 697537.

This commit is contained in:
Brian Hackett 2011-10-27 11:14:56 -07:00
Родитель 5a1e8e571a
Коммит f749fa5ea8
11 изменённых файлов: 115 добавлений и 67 удалений

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

@ -641,7 +641,7 @@ InitTypeConstructor(JSContext* cx,
JSObject*& typeProto,
JSObject*& dataProto)
{
JSFunction* fun = JS_DefineFunction(cx, parent, spec.name, spec.call,
JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call,
spec.nargs, spec.flags);
if (!fun)
return false;
@ -672,8 +672,7 @@ InitTypeConstructor(JSContext* cx,
// Stash ctypes.{Pointer,Array,Struct}Type.prototype on a reserved slot of
// the type constructor, for faster lookup.
if (!JS_SetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto)))
return false;
js::SetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto));
// Create an object to serve as the common ancestor for all CData objects
// created from the given type constructor. This has ctypes.CData.prototype
@ -721,14 +720,18 @@ InitInt64Class(JSContext* cx,
if (!JS_FreezeObject(cx, ctor))
return NULL;
// Stash ctypes.{Int64,UInt64}.prototype on a reserved slot of the 'join'
// function.
jsval join;
ASSERT_OK(JS_GetProperty(cx, ctor, "join", &join));
if (!JS_SetReservedSlot(cx, JSVAL_TO_OBJECT(join), SLOT_FN_INT64PROTO,
OBJECT_TO_JSVAL(prototype)))
// Redefine the 'join' function as an extended native and stash
// ctypes.{Int64,UInt64}.prototype in a reserved slot of the new function.
JS_ASSERT(clasp == &sInt64ProtoClass || clasp == &sUInt64ProtoClass);
JSNative native = (clasp == &sInt64ProtoClass) ? Int64::Join : UInt64::Join;
JSFunction* fun = js::DefineFunctionWithReserved(cx, ctor, "join", native,
2, CTYPESFN_FLAGS);
if (!fun)
return NULL;
js::SetFunctionNativeReserved(fun, SLOT_FN_INT64PROTO,
OBJECT_TO_JSVAL(prototype));
if (!JS_FreezeObject(cx, prototype))
return NULL;
@ -3030,8 +3033,7 @@ CType::GetProtoFromCtor(JSContext* cx, JSObject* obj, CTypeProtoSlot slot)
{
// Get ctypes.{Pointer,Array,Struct}Type.prototype from a reserved slot
// on the type constructor.
jsval protoslot;
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FN_CTORPROTO, &protoslot));
jsval protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO);
JSObject* proto = JSVAL_TO_OBJECT(protoslot);
JS_ASSERT(proto);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sCTypeProtoClass);
@ -6242,8 +6244,7 @@ Int64::Join(JSContext* cx, uintN argc, jsval* vp)
// Get Int64.prototype from the function's reserved slot.
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
jsval slot;
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
@ -6410,8 +6411,7 @@ UInt64::Join(JSContext* cx, uintN argc, jsval* vp)
// Get UInt64.prototype from the function's reserved slot.
JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
jsval slot;
ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
JSObject* proto = JSVAL_TO_OBJECT(slot);
JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);

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

@ -4290,12 +4290,7 @@ JS_NewFunctionById(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSO
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
/* Allow natives created through this interface to use {Get,Set}FunctionNativeReserved. */
AllocKind kind = native
? (AllocKind) JSFunction::ExtendedFinalizeKind
: (AllocKind) JSFunction::FinalizeKind;
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id), kind);
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id));
}
JS_PUBLIC_API(JSObject *)

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

@ -207,6 +207,46 @@ js::IsOriginalScriptFunction(JSFunction *fun)
return fun->script()->function() == fun;
}
JS_FRIEND_API(JSFunction *)
js::DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
if (!atom)
return NULL;
return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), call, nargs, attrs,
JSFunction::ExtendedFinalizeKind);
}
JS_FRIEND_API(JSFunction *)
js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
jsid id)
{
JS_ASSERT(JSID_IS_STRING(id));
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id),
JSFunction::ExtendedFinalizeKind);
}
JS_FRIEND_API(JSObject *)
js::InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JSClass *clasp, JSNative constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, parent_proto);
return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
nargs, ps, fs, static_ps, static_fs, NULL,
JSFunction::ExtendedFinalizeKind);
}
JS_FRIEND_API(const Value &)
js::GetFunctionNativeReserved(JSObject *fun, size_t which)
{

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

@ -276,6 +276,20 @@ GetObjectGlobal(JSObject *obj);
JS_FRIEND_API(bool)
IsOriginalScriptFunction(JSFunction *fun);
JS_FRIEND_API(JSFunction *)
DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs);
JS_FRIEND_API(JSFunction *)
NewFunctionByIdWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags,
JSObject *parent, jsid id);
JS_FRIEND_API(JSObject *)
InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JSClass *clasp, JSNative constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
JS_FRIEND_API(const Value &)
GetFunctionNativeReserved(JSObject *fun, size_t which);

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

@ -4243,7 +4243,7 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp)
JSObject **ctorp, AllocKind ctorKind)
{
/*
* Create a prototype object for this class.
@ -4316,7 +4316,8 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
* perhaps as part of bug 638316.)
*/
JSFunction *fun =
js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom);
js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
ctorKind);
if (!fun)
goto bad;
fun->setConstructorClass(clasp);
@ -4431,7 +4432,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
Class *clasp, Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp)
JSObject **ctorp, AllocKind ctorKind)
{
JSAtom *atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
if (!atom)
@ -4457,7 +4458,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
}
return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
ps, fs, static_ps, static_fs, ctorp);
ps, fs, static_ps, static_fs, ctorp, ctorKind);
}
void

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

@ -1517,14 +1517,6 @@ extern JSFunctionSpec object_static_methods[];
namespace js {
JSObject *
DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
JSObject *protoProto, Class *clasp,
Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp = NULL);
bool
IsStandardClassResolved(JSObject *obj, js::Class *clasp);
@ -1533,13 +1525,6 @@ MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp);
}
extern JSObject *
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
js::Class *clasp, JSNative constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp = NULL);
/*
* Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
*/

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

@ -1939,8 +1939,25 @@ ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
return false;
}
JSObject *
DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
JSObject *protoProto, Class *clasp,
Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp = NULL,
gc::AllocKind ctorKind = JSFunction::FinalizeKind);
} /* namespace js */
extern JSObject *
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
js::Class *clasp, JSNative constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp = NULL,
js::gc::AllocKind ctorKind = JSFunction::FinalizeKind);
inline JSObject *
js_GetProtoIfDenseArray(JSObject *obj)
{

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

@ -647,20 +647,25 @@ class Worker : public WorkerParent
// alive, this postMessage function cannot be called after the Worker
// is collected. Therefore it's safe to stash a pointer (a weak
// reference) to the C++ Worker object in the reserved slot.
post = JS_GetFunctionObject(JS_DefineFunction(context, global, "postMessage",
(JSNative) jsPostMessageToParent, 1, 0));
if (!post || !JS_SetReservedSlot(context, post, 0, PRIVATE_TO_JSVAL(this)))
post = JS_GetFunctionObject(
js::DefineFunctionWithReserved(context, global, "postMessage",
(JSNative) jsPostMessageToParent, 1, 0));
if (!post)
goto bad;
proto = JS_InitClass(context, global, NULL, &jsWorkerClass, jsConstruct, 1,
NULL, jsMethods, NULL, NULL);
js::SetFunctionNativeReserved(post, 0, PRIVATE_TO_JSVAL(this));
proto = js::InitClassWithReserved(context, global, NULL, &jsWorkerClass, jsConstruct, 1,
NULL, jsMethods, NULL, NULL);
if (!proto)
goto bad;
ctor = JS_GetConstructor(context, proto);
if (!ctor || !JS_SetReservedSlot(context, ctor, 0, PRIVATE_TO_JSVAL(this)))
if (!ctor)
goto bad;
js::SetFunctionNativeReserved(post, 0, PRIVATE_TO_JSVAL(this));
JS_EndRequest(context);
JS_ClearContextThread(context);
return true;
@ -806,23 +811,17 @@ class Worker : public WorkerParent
}
static bool getWorkerParentFromConstructor(JSContext *cx, JSObject *ctor, WorkerParent **p) {
jsval v;
if (!JS_GetReservedSlot(cx, ctor, 0, &v))
return false;
jsval v = js::GetFunctionNativeReserved(ctor, 0);
if (JSVAL_IS_VOID(v)) {
// This means ctor is the root Worker constructor (created in
// Worker::initWorkers as opposed to Worker::createContext, which sets up
// Worker sandboxes) and nothing is initialized yet.
if (!JS_GetReservedSlot(cx, ctor, 1, &v))
return false;
v = js::GetFunctionNativeReserved(ctor, 1);
ThreadPool *threadPool = (ThreadPool *) JSVAL_TO_PRIVATE(v);
if (!threadPool->start(cx))
return false;
WorkerParent *parent = threadPool->getMainQueue();
if (!JS_SetReservedSlot(cx, ctor, 0, PRIVATE_TO_JSVAL(parent))) {
threadPool->shutdown(cx);
return false;
}
js::SetFunctionNativeReserved(ctor, 0, PRIVATE_TO_JSVAL(parent));
*p = parent;
return true;
}
@ -861,17 +860,16 @@ class Worker : public WorkerParent
*objp = threadPool->asObject();
// Create the Worker constructor.
JSObject *proto = JS_InitClass(cx, global, NULL, &jsWorkerClass,
jsConstruct, 1,
NULL, jsMethods, NULL, NULL);
JSObject *proto = js::InitClassWithReserved(cx, global, NULL, &jsWorkerClass,
jsConstruct, 1,
NULL, jsMethods, NULL, NULL);
if (!proto)
return NULL;
// Stash a pointer to the ThreadPool in constructor reserved slot 1.
// It will be used later when lazily creating the MainQueue.
JSObject *ctor = JS_GetConstructor(cx, proto);
if (!JS_SetReservedSlot(cx, ctor, 1, PRIVATE_TO_JSVAL(threadPool)))
return NULL;
js::SetFunctionNativeReserved(ctor, 1, PRIVATE_TO_JSVAL(threadPool));
return threadPool;
}
@ -1155,9 +1153,7 @@ Worker::processOneEvent()
JSBool
Worker::jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp)
{
jsval workerval;
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &workerval))
return false;
jsval workerval = js::GetFunctionNativeReserved(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0);
Worker *w = (Worker *) JSVAL_TO_PRIVATE(workerval);
{

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

@ -3879,8 +3879,8 @@ FunctionWrapper(JSContext *cx, uintN argc, jsval *vp)
JSBool
WrapCallable(JSContext *cx, JSObject *obj, jsid id, JSObject *propobj, jsval *vp)
{
JSFunction *fun = JS_NewFunctionById(cx, FunctionWrapper, 0, 0,
JS_GetGlobalForObject(cx, obj), id);
JSFunction *fun = js::NewFunctionByIdWithReserved(cx, FunctionWrapper, 0, 0,
JS_GetGlobalForObject(cx, obj), id);
if (!fun)
return JS_FALSE;

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

@ -186,7 +186,7 @@ GeneratePropertyOp(JSContext *cx, JSObject *obj, jsid id, uintN argc, Op pop)
// The JS engine provides two reserved slots on function objects for
// XPConnect to use. Use them to stick the necessary info here.
JSFunction *fun =
JS_NewFunctionById(cx, PropertyOpForwarder<Op>, argc, 0, obj, id);
js::NewFunctionByIdWithReserved(cx, PropertyOpForwarder<Op>, argc, 0, obj, id);
if (!fun)
return JS_FALSE;

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

@ -160,7 +160,7 @@ XPCNativeMember::Resolve(XPCCallContext& ccx, XPCNativeInterface* iface,
callback = XPC_WN_GetterSetter;
}
JSFunction *fun = JS_NewFunctionById(ccx, callback, argc, 0, parent, GetName());
JSFunction *fun = js::NewFunctionByIdWithReserved(ccx, callback, argc, 0, parent, GetName());
if (!fun)
return JS_FALSE;