Bug 784400 - Give self-hosted code access to standard builtins. r=luke
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4996,16 +4996,26 @@ JS_DefineFunctions(JSContext *cx, JSObje
/*
* As jsapi.h notes, fs must point to storage that lives as long
* as fun->object lives.
*/
fun->setExtendedSlot(0, PrivateValue(fs));
}
+ /*
+ * During creation of the self-hosting global, we ignore all
+ * self-hosted functions, as that means we're currently setting up
+ * the global object that that the self-hosted code is then compiled
+ * in. Self-hosted functions can access each other via their names,
+ * but not via the builtin classes they get installed into.
+ */
+ if (fs->selfHostedName && cx->runtime->isSelfHostedGlobal(cx->global()))
+ return JS_TRUE;
+
fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags, fs->selfHostedName);
if (!fun)
return JS_FALSE;
if (fs->call.info)
fun->setJitInfo(fs->call.info);
}
return JS_TRUE;
}
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -237,43 +237,45 @@ JSRuntime::createJaegerRuntime(JSContext
}
#endif
static void
selfHosting_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
PrintError(cx, stderr, message, report, true);
}
+
static JSClass self_hosting_global_class = {
"self-hosting-global", JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub,
JS_ConvertStub, NULL
};
+
bool
JSRuntime::initSelfHosting(JSContext *cx)
{
JS_ASSERT(!selfHostedGlobal_);
RootedObject savedGlobal(cx, JS_GetGlobalObject(cx));
if (!(selfHostedGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL)))
return false;
JS_SetGlobalObject(cx, selfHostedGlobal_);
- RootedObject shg(cx, selfHostedGlobal_);
CompileOptions options(cx);
options.setFileAndLine("self-hosted", 1);
options.setSelfHostingMode(true);
/*
* Set a temporary error reporter printing to stderr because it is too
* early in the startup process for any other reporter to be registered
* and we don't want errors in self-hosted code to be silently swallowed.
*/
JSErrorReporter oldReporter = JS_SetErrorReporter(cx, selfHosting_ErrorReporter);
+ RootedObject shg(cx, selfHostedGlobal_);
Value rv;
bool ok;
char *filename = getenv("MOZ_SELFHOSTEDJS");
if (filename) {
RootedScript script(cx, Compile(cx, shg, options, filename));
if (script)
ok = Execute(cx, script, *shg.get(), &rv);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -466,16 +466,19 @@ struct JSRuntime : js::RuntimeFriendFiel
js::mjit::JaegerRuntime &jaegerRuntime() {
JS_ASSERT(hasJaegerRuntime());
return *jaegerRuntime_;
}
#endif
bool initSelfHosting(JSContext *cx);
void markSelfHostedGlobal(JSTracer *trc);
+ bool isSelfHostedGlobal(js::HandleObject global) {
+ return global == selfHostedGlobal_;
+ }
JSFunction *getSelfHostedFunction(JSContext *cx, const char *name);
bool cloneSelfHostedValueById(JSContext *cx, js::HandleId id, js::HandleObject holder,
js::MutableHandleValue vp);
/* Base address of the native stack for the current thread. */
uintptr_t nativeStackBase;
/* The native stack size limit that runtime should not exceed. */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1563,16 +1563,17 @@ js_DefineFunction(JSContext *cx, HandleO
if (native) {
JS_ASSERT(!selfHostedName);
RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
fun = js_NewFunction(cx, NullPtr(), native, nargs,
attrs & (JSFUN_FLAGS_MASK),
obj, atom, kind);
} else {
JS_ASSERT(attrs & JSFUN_INTERPRETED);
+ JS_ASSERT(!cx->runtime->isSelfHostedGlobal(cx->global()));
fun = cx->runtime->getSelfHostedFunction(cx, selfHostedName);
fun->initAtom(JSID_TO_ATOM(id));
}
if (!fun)
return NULL;
RootedValue funVal(cx, ObjectValue(*fun));
if (!JSObject::defineGeneric(cx, obj, id, funVal, gop, sop, attrs & ~JSFUN_FLAGS_MASK))
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -451,16 +451,24 @@ GlobalObject::initFunctionAndObjectClass
self->setThrowTypeError(throwTypeError);
RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self));
if (!intrinsicsHolder)
return NULL;
self->setIntrinsicsHolder(intrinsicsHolder);
if (!JS_DefineFunctions(cx, intrinsicsHolder, intrinsic_functions))
return NULL;
+ /* Define a property 'global' with the current global as its value. */
+ RootedValue global(cx, OBJECT_TO_JSVAL(self));
+ if (!JSObject::defineProperty(cx, intrinsicsHolder, cx->names().global,
+ global, JS_PropertyStub, JS_StrictPropertyStub,
+ JSPROP_PERMANENT | JSPROP_READONLY))
+ {
+ return NULL;
+ }
/*
* The global object should have |Object.prototype| as its [[Prototype]].
* Eventually we'd like to have standard classes be there from the start,
* and thus we would know we were always setting what had previously been a
* null [[Prototype]], but right now some code assumes it can set the
* [[Prototype]] before standard classes have been initialized. For now,
* only set the [[Prototype]] if it hasn't already been set.