From 7c51226165002c7218e5cff66eba994e5d201d33 Mon Sep 17 00:00:00 2001 From: Till Schneidereit Date: Wed, 29 Aug 2012 00:11:13 +0200 Subject: [PATCH] Bug 785645 - Support constructors in self-hosted JavaScript. r=luke --HG-- extra : rebase_source : 9d56165f8875d0ebb8d89e88d92492c21fc6b74c --- js/src/jsapi.h | 10 +++++++--- js/src/jscntxt.cpp | 18 +++++++++++++----- js/src/jsfun.h | 6 ++++-- js/src/vm/GlobalObject.cpp | 21 +++++++++++++++++---- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index b39601caca6c..9746cfabaf03 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -2527,10 +2527,14 @@ class AutoIdRooter : private AutoGCRooter /* Function flags, internal use only, returned by JS_GetFunctionFlags. */ #define JSFUN_LAMBDA 0x08 /* expressed, not declared, function */ -#define JSFUN_SELF_HOSTED 0x40 /* function is self-hosted native and +#define JSFUN_SELF_HOSTED 0x20 /* function is self-hosted builtin and must not be decompilable nor constructible. */ +#define JSFUN_SELF_HOSTED_CTOR 0x40 /* function is self-hosted builtin + constructor and must be constructible + but not decompilable. */ + #define JSFUN_HEAVYWEIGHT 0x80 /* activation requires a Call object */ #define JSFUN_HEAVYWEIGHT_TEST(f) ((f) & JSFUN_HEAVYWEIGHT) @@ -2541,11 +2545,11 @@ class AutoIdRooter : private AutoGCRooter #define JSFUN_HAS_DEFAULTS 0x0400 /* function has at least one default parameter */ -#define JSFUN_FLAGS_MASK 0x07f8 /* overlay JSFUN_* attributes -- +#define JSFUN_FLAGS_MASK 0x07f8 /* overlay JSFUN_* attributes -- bits 12-15 are used internally to flag interpreted functions */ -#define JSFUN_STUB_GSOPS 0x1000 /* use JS_PropertyStub getter/setter +#define JSFUN_STUB_GSOPS 0x1000 /* use JS_PropertyStub getter/setter instead of defaulting to class gsops for property holding function */ diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e2be53dbe36b..2a98360c011d 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -267,11 +267,19 @@ JSRuntime::cloneSelfHostedValueById(JSContext *cx, jsid id, HandleObject holder, return false; } - RootedObject clone(cx, JS_CloneFunctionObject(cx, &funVal.toObject(), cx->global())); - if (!clone) - return false; - - vp->setObjectOrNull(clone); + /* + * We don't clone if we're operating in the self-hosting global, as that + * means we're currently executing the self-hosting script while + * initializing the runtime (see JSRuntime::initSelfHosting). + */ + if (cx->global() == selfHostedGlobal_) { + *vp = ObjectValue(funVal.toObject()); + } else { + RootedObject clone(cx, JS_CloneFunctionObject(cx, &funVal.toObject(), cx->global())); + if (!clone) + return false; + *vp = ObjectValue(*clone); + } DebugOnly ok = JS_DefinePropertyById(cx, holder, id, *vp, NULL, NULL, 0); JS_ASSERT(ok); return true; diff --git a/js/src/jsfun.h b/js/src/jsfun.h index 8490f86a6e4a..2f1c8d19ac71 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -80,12 +80,14 @@ struct JSFunction : public JSObject bool hasGuessedAtom() const { return flags & JSFUN_HAS_GUESSED_ATOM; } bool isInterpreted() const { return flags & JSFUN_INTERPRETED; } bool isNative() const { return !isInterpreted(); } - bool isSelfHostedBuiltin() const { return flags & JSFUN_SELF_HOSTED; } + bool isSelfHostedBuiltin() const { return flags & JSFUN_SELF_HOSTED; } + bool isSelfHostedConstructor() const { return flags & JSFUN_SELF_HOSTED_CTOR; } bool isNativeConstructor() const { return flags & JSFUN_CONSTRUCTOR; } bool isHeavyweight() const { return JSFUN_HEAVYWEIGHT_TEST(flags); } bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; } bool isInterpretedConstructor() const { - return isInterpreted() && !isFunctionPrototype() && !isSelfHostedBuiltin(); + return isInterpreted() && !isFunctionPrototype() && + (!isSelfHostedBuiltin() || isSelfHostedConstructor()); } bool isNamedLambda() const { return (flags & JSFUN_LAMBDA) && atom_ && !hasGuessedAtom(); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 1f3ef3b5f4d9..b399ee005b38 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -231,11 +231,24 @@ intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp) return false; } +static JSBool +intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + JS_ASSERT(args.length() >= 1); + JS_ASSERT(args[0].isObject()); + RootedObject obj(cx, &args[0].toObject()); + JS_ASSERT(obj->isFunction()); + obj->toFunction()->flags |= JSFUN_SELF_HOSTED_CTOR; + return true; +} + JSFunctionSpec intrinsic_functions[] = { - JS_FN("ToObject", intrinsic_ToObject, 1,0), - JS_FN("ToInteger", intrinsic_ToInteger, 1,0), - JS_FN("IsCallable", intrinsic_IsCallable, 1,0), - JS_FN("ThrowError", intrinsic_ThrowError, 4,0), + JS_FN("ToObject", intrinsic_ToObject, 1,0), + JS_FN("ToInteger", intrinsic_ToInteger, 1,0), + JS_FN("IsCallable", intrinsic_IsCallable, 1,0), + JS_FN("ThrowError", intrinsic_ThrowError, 4,0), + JS_FN("_MakeConstructible", intrinsic_MakeConstructible, 1,0), JS_FS_END }; JSObject *