Bug 944975: fix bug by getting original fcn for callsite clone in New (r=shu).
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Fri, 07 Feb 2014 17:56:38 +0100
changeset 167562 414676ce184c530e9bc8255aa77e09584643eb0d
parent 167561 eddf0ede2cb2c4b47ace7ae3a623dc0e6542f3e9
child 167563 6df8e0c99c787b6f1826f026b36e80a185c2c602
push id26174
push userkwierso@gmail.com
push dateSat, 08 Feb 2014 00:55:48 +0000
treeherdermozilla-central@2c873eff7dc2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs944975
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 944975: fix bug by getting original fcn for callsite clone in New (r=shu).
js/src/jsfun.cpp
js/src/jsfun.h
js/src/vm/Interpreter.cpp
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -113,18 +113,18 @@ fun_getProperty(JSContext *cx, HandleObj
         ++iter;
         if (iter.done() || !iter.isFunctionFrame()) {
             JS_ASSERT(vp.isNull());
             return true;
         }
 
         /* Callsite clones should never escape to script. */
         JSObject &maybeClone = iter.calleev().toObject();
-        if (maybeClone.is<JSFunction>() && maybeClone.as<JSFunction>().nonLazyScript()->isCallsiteClone())
-            vp.setObject(*maybeClone.as<JSFunction>().nonLazyScript()->originalFunction());
+        if (maybeClone.is<JSFunction>())
+            vp.setObject(*maybeClone.as<JSFunction>().originalFunction());
         else
             vp.set(iter.calleev());
 
         if (!cx->compartment()->wrap(cx, vp))
             return false;
 
         /*
          * Censor the caller if we don't have full access to it.
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -334,16 +334,26 @@ class JSFunction : public JSObject
     JSScript *nonLazyScript() const {
         js::AutoThreadSafeAccess ts(this);
         JS_ASSERT(js::CurrentThreadCanReadCompilationData());
         JS_ASSERT(hasScript());
         JS_ASSERT(u.i.s.script_);
         return u.i.s.script_;
     }
 
+    // Returns the non-callsited-clone version of this function.  Use
+    // when return-value can flow to arbitrary JS (see Bug 944975).
+    JSFunction* originalFunction() {
+        if (this->hasScript() && this->nonLazyScript()->isCallsiteClone()) {
+            return this->nonLazyScript()->originalFunction();
+        } else {
+            return this;
+        }
+    }
+
     js::HeapPtrScript &mutableScript() {
         JS_ASSERT(isInterpreted());
         return *(js::HeapPtrScript *)&u.i.s.script_;
     }
 
     js::LazyScript *lazyScript() const {
         js::AutoThreadSafeAccess ts(this);
         JS_ASSERT(isInterpretedLazy() && u.i.s.lazy_);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -550,19 +550,20 @@ js::InvokeConstructor(JSContext *cx, Cal
     if (callee.is<JSFunction>()) {
         RootedFunction fun(cx, &callee.as<JSFunction>());
 
         if (fun->isNativeConstructor()) {
             bool ok = CallJSNativeConstructor(cx, fun->native(), args);
             return ok;
         }
 
-        if (!fun->isInterpretedConstructor())
-            return ReportIsNotFunction(cx, args.calleev(), args.length() + 1, CONSTRUCT);
-
+        if (!fun->isInterpretedConstructor()) {
+            RootedValue orig(cx, ObjectValue(*fun->originalFunction()));
+            return ReportIsNotFunction(cx, orig, args.length() + 1, CONSTRUCT);
+        }
         if (!Invoke(cx, args, CONSTRUCT))
             return false;
 
         JS_ASSERT(args.rval().isObject());
         return true;
     }
 
     const Class *clasp = callee.getClass();