Bug 1061961: Fully initialize ScriptSourceObjects built by XDR and for Function.prototype. r=shu
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Source-introductionScript-04.js
@@ -0,0 +1,8 @@
+// Function.prototype's script source should be fully initialized.
+var g = newGlobal();
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+
+var DOfp = gw.getOwnPropertyDescriptor('Function').value.proto;
+// This should not crash.
+print(DOfp.script.source.introductionScript);
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -824,17 +824,17 @@ CreateFunctionPrototype(JSContext *cx, J
return nullptr;
}
ScriptSourceHolder ssHolder(ss);
ss->setSource(source, sourceLen);
CompileOptions options(cx);
options.setNoScriptRval(true)
.setVersion(JSVERSION_DEFAULT);
RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, ss));
- if (!sourceObject)
+ if (!sourceObject || !ScriptSourceObject::initFromOptions(cx, sourceObject, options))
return nullptr;
RootedScript script(cx, JSScript::Create(cx,
/* enclosingScope = */ js::NullPtr(),
/* savedCallerFun = */ false,
options,
/* staticLevel = */ 0,
sourceObject,
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -696,17 +696,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
* ScriptSourceObject. Most CompileOptions fields aren't used by
* ScriptSourceObject, and those that are (element; elementAttributeName)
* aren't preserved by XDR. So this can be simple.
*/
CompileOptions options(cx);
options.setOriginPrincipals(xdr->originPrincipals());
ss->initFromOptions(cx, options);
sourceObject = ScriptSourceObject::create(cx, ss);
- if (!sourceObject)
+ if (!sourceObject ||
+ !ScriptSourceObject::initFromOptions(cx, sourceObject, options))
return false;
} else {
JS_ASSERT(enclosingScript);
// When decoding, all the scripts and the script source object
// are in the same compartment, so the script's source object
// should never be a cross-compartment wrapper.
JS_ASSERT(enclosingScript->sourceObject()->is<ScriptSourceObject>());
sourceObject = &enclosingScript->sourceObject()->as<ScriptSourceObject>();
@@ -1300,16 +1301,19 @@ ScriptSourceObject::create(ExclusiveCont
return sourceObject;
}
/* static */ bool
ScriptSourceObject::initFromOptions(JSContext *cx, HandleScriptSource source,
const ReadOnlyCompileOptions &options)
{
assertSameCompartment(cx, source);
+ MOZ_ASSERT(source->getReservedSlot(ELEMENT_SLOT).isMagic(JS_GENERIC_MAGIC));
+ MOZ_ASSERT(source->getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic(JS_GENERIC_MAGIC));
+ MOZ_ASSERT(source->getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isMagic(JS_GENERIC_MAGIC));
RootedValue element(cx, ObjectOrNullValue(options.element()));
if (!cx->compartment()->wrap(cx, &element))
return false;
source->setReservedSlot(ELEMENT_SLOT, element);
RootedValue elementAttributeName(cx);
if (options.elementAttributeName())
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -651,16 +651,17 @@ class ScriptSourceObject : public JSObje
ScriptSource *source() const {
return static_cast<ScriptSource *>(getReservedSlot(SOURCE_SLOT).toPrivate());
}
JSObject *element() const {
return getReservedSlot(ELEMENT_SLOT).toObjectOrNull();
}
const Value &elementAttributeName() const {
+ MOZ_ASSERT(!getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic());
return getReservedSlot(ELEMENT_PROPERTY_SLOT);
}
JSScript *introductionScript() const {
if (getReservedSlot(INTRODUCTION_SCRIPT_SLOT).isUndefined())
return nullptr;
void *untyped = getReservedSlot(INTRODUCTION_SCRIPT_SLOT).toPrivate();
MOZ_ASSERT(untyped);
return static_cast<JSScript *>(untyped);