Bug 1061961: Fully initialize ScriptSourceObjects built by XDR and for Function.prototype. r=shu
authorJim Blandy <jimb@mozilla.com>
Thu, 04 Sep 2014 15:40:10 -0700
changeset 203714 d052bb1a13b8ab453725984232de9bc87d0f91bd
parent 203713 4b99d99e7d914561800b8c1c7b758c0f0e07b0cc
child 203715 0d8adc6d6faacb7a29a187b40833747f6935ea67
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersshu
bugs1061961
milestone35.0a1
Bug 1061961: Fully initialize ScriptSourceObjects built by XDR and for Function.prototype. r=shu
js/src/jit-test/tests/debug/Source-introductionScript-04.js
js/src/jsfun.cpp
js/src/jsscript.cpp
js/src/jsscript.h
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);