Bug 787927 - Prevent self-hosted JS script from being registered with the debugger. r=jimb, a=lsblakk
authorTill Schneidereit <tschneidereit@gmail.com>
Mon, 03 Sep 2012 16:04:14 +0200
changeset 132373 4b062091ea4ea910e660d7545fdeb3c4e67f9b3a
parent 132372 4e414cc5ca5a95f844e3821b8f9995240b4fee34
child 132374 669a4b33fa4bad757d840b40e99b69132007d573
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb, lsblakk
bugs787927
milestone21.0a2
Bug 787927 - Prevent self-hosted JS script from being registered with the debugger. r=jimb, a=lsblakk
js/src/frontend/BytecodeEmitter.cpp
js/src/jsdbgapi.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/vm/Debugger.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4451,16 +4451,17 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
 
         // Inherit most things (principals, version, etc) from the parent.
         Rooted<JSScript*> parent(cx, bce->script);
         Rooted<JSObject*> enclosingScope(cx, EnclosingStaticScope(bce));
         CompileOptions options(cx);
         options.setPrincipals(parent->principals())
                .setOriginPrincipals(parent->originPrincipals)
                .setCompileAndGo(parent->compileAndGo)
+               .setSelfHostingMode(parent->selfHosted)
                .setNoScriptRval(false)
                .setVersion(parent->getVersion())
                .setUserBit(parent->userBit);
         Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
                                                       parent->staticLevel + 1,
                                                       bce->script->scriptSource(),
                                                       funbox->bufStart, funbox->bufEnd));
         if (!script)
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1037,16 +1037,18 @@ js_CallContextDebugHandler(JSContext *cx
 
 JS_PUBLIC_API(StackDescription *)
 JS::DescribeStack(JSContext *cx, unsigned maxFrames)
 {
     AutoAssertNoGC nogc;
     Vector<FrameDescription> frames(cx);
 
     for (ScriptFrameIter i(cx); !i.done(); ++i) {
+        if (i.script()->selfHosted)
+            continue;
         FrameDescription desc;
         desc.script = i.script();
         desc.lineno = PCToLineNumber(i.script(), i.pc());
         desc.fun = i.maybeCallee();
         if (!frames.append(desc))
             return NULL;
         if (frames.length() == maxFrames)
             break;
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1715,16 +1715,17 @@ JSScript::Create(JSContext *cx, HandleOb
             = options.originPrincipals ? options.originPrincipals : options.principals;
         JS_HoldPrincipals(script->originPrincipals);
     } else if (options.originPrincipals) {
         script->originPrincipals = options.originPrincipals;
         JS_HoldPrincipals(script->originPrincipals);
     }
 
     script->compileAndGo = options.compileAndGo;
+    script->selfHosted = options.selfHostingMode;
     script->noScriptRval = options.noScriptRval;
 
     script->version = options.version;
     JS_ASSERT(script->getVersion() == options.version);     // assert that no overflow occurred
 
     // This is an unsigned-to-uint16_t conversion, test for too-high values.
     // In practice, recursion in Parser and/or BytecodeEmitter will blow the
     // stack if we nest functions more than a few hundred deep, so this will
@@ -2010,28 +2011,34 @@ JSScript::enclosingScriptsCompiledSucces
         }
     }
     return true;
 }
 
 void
 js::CallNewScriptHook(JSContext *cx, HandleScript script, HandleFunction fun)
 {
+    if (script->selfHosted)
+        return;
+
     AssertCanGC();
     JS_ASSERT(!script->isActiveEval);
     if (JSNewScriptHook hook = cx->runtime->debugHooks.newScriptHook) {
         AutoKeepAtoms keep(cx->runtime);
         hook(cx, script->filename, script->lineno, script, fun,
              cx->runtime->debugHooks.newScriptHookData);
     }
 }
 
 void
 js::CallDestroyScriptHook(FreeOp *fop, RawScript script)
 {
+    if (script->selfHosted)
+        return;
+
     // The hook will only call into JS if a GC is not running.
     if (JSDestroyScriptHook hook = fop->runtime()->debugHooks.destroyScriptHook)
         hook(fop, script, fop->runtime()->debugHooks.destroyScriptHookData);
     script->clearTraps(fop);
 }
 
 void
 JSScript::finalize(FreeOp *fop)
@@ -2376,16 +2383,17 @@ js::CloneScript(JSContext *cx, HandleObj
     }
 
     /* Now that all fallible allocation is complete, create the GC thing. */
 
     CompileOptions options(cx);
     options.setPrincipals(cx->compartment->principals)
            .setOriginPrincipals(src->originPrincipals)
            .setCompileAndGo(src->compileAndGo)
+           .setSelfHostingMode(src->selfHosted)
            .setNoScriptRval(src->noScriptRval)
            .setVersion(src->getVersion())
            .setUserBit(src->userBit);
     RootedScript dst(cx, JSScript::Create(cx, enclosingScope, src->savedCallerFun,
                                           options, src->staticLevel,
                                           src->scriptSource(), src->sourceStart, src->sourceEnd));
     if (!dst) {
         js_free(data);
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -461,16 +461,17 @@ class JSScript : public js::gc::Cell
 
   public:
     bool            noScriptRval:1; /* no need for result value of last
                                        expression statement */
     bool            savedCallerFun:1; /* can call getCallerFunction() */
     bool            strict:1; /* code is in strict mode */
     bool            explicitUseStrict:1; /* code has "use strict"; explicitly */
     bool            compileAndGo:1;   /* see Parser::compileAndGo */
+    bool            selfHosted:1;     /* see Parser::selfHostingMode */
     bool            bindingsAccessedDynamically:1; /* see ContextFlags' field of the same name */
     bool            funHasExtensibleScope:1;       /* see ContextFlags' field of the same name */
     bool            funHasAnyAliasedFormal:1;      /* true if any formalIsAliased(i) */
     bool            warnedAboutTwoArgumentEval:1; /* have warned about use of
                                                      obsolete eval(s, o) in
                                                      this script */
     bool            warnedAboutUndefinedProp:1; /* have warned about uses of
                                                    undefined properties in this
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1082,16 +1082,19 @@ AddNewScriptRecipients(GlobalObject::Deb
         }
     }
     return true;
 }
 
 void
 Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *compileAndGoGlobal_)
 {
+    if (script->selfHosted)
+        return;
+
     Rooted<GlobalObject*> compileAndGoGlobal(cx, compileAndGoGlobal_);
 
     JS_ASSERT(script->compileAndGo == !!compileAndGoGlobal);
 
     /*
      * Build the list of recipients. For compile-and-go scripts, this is the
      * same as the generic Debugger::dispatchHook code, but non-compile-and-go
      * scripts are not tied to particular globals. We deliver them to every
@@ -2469,17 +2472,17 @@ class Debugger::ScriptQuery {
     }
 
     /*
      * If |script| matches this query, append it to |vector| or place it in
      * |innermostForCompartment|, as appropriate. Set |oom| if an out of memory
      * condition occurred.
      */
     void consider(JSScript *script) {
-        if (oom)
+        if (oom || script->selfHosted)
             return;
         JSCompartment *compartment = script->compartment();
         if (!compartments.has(compartment))
             return;
         if (urlCString.ptr()) {
             if (!script->filename || strcmp(script->filename, urlCString.ptr()) != 0)
                 return;
         }
@@ -3139,17 +3142,17 @@ DebuggerScript_getLineOffsets(JSContext 
     return true;
 }
 
 bool
 Debugger::observesScript(JSScript *script) const
 {
     if (!enabled)
         return false;
-    return observesGlobal(&script->global());
+    return observesGlobal(&script->global()) && !script->selfHosted;
 }
 
 static JSBool
 DebuggerScript_setBreakpoint(JSContext *cx, unsigned argc, Value *vp)
 {
     REQUIRE_ARGC("Debugger.Script.setBreakpoint", 2);
     THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "setBreakpoint", args, obj, script);
     Debugger *dbg = Debugger::fromChildJSObject(obj);
@@ -4081,17 +4084,17 @@ DebuggerObject_getScript(JSContext *cx, 
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "get script", args, dbg, obj);
 
     if (!obj->isFunction()) {
         args.rval().setUndefined();
         return true;
     }
 
     RootedFunction fun(cx, obj->toFunction());
-    if (!fun->isInterpreted()) {
+    if (fun->isBuiltin()) {
         args.rval().setUndefined();
         return true;
     }
 
     RootedScript script(cx, fun->nonLazyScript());
     RootedObject scriptObject(cx, dbg->wrapScript(cx, script));
     if (!scriptObject)
         return false;