Bug 1089026 part 2. Refactor the CompileFunction code to allow cleanly separating whether we're passing in an object to define the function on or a scope chain. This change should not cause any behavior changes. r=shu
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 30 Oct 2014 19:40:28 -0400
changeset 213254 dd4ec08078387e78ee34a33432a03bdc3675f882
parent 213253 2887e7c320feed62cb66ff49327d37d13ad81276
child 213255 cb53a4bac4c8c778823cec7c0769e6e894e6c0c5
push id51182
push userbzbarsky@mozilla.com
push dateThu, 30 Oct 2014 23:40:47 +0000
treeherdermozilla-inbound@715ded1f9639 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1089026
milestone36.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 1089026 part 2. Refactor the CompileFunction code to allow cleanly separating whether we're passing in an object to define the function on or a scope chain. This change should not cause any behavior changes. r=shu
js/src/jsapi.cpp
js/src/jsapi.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4582,70 +4582,92 @@ JS_GetFunctionScript(JSContext *cx, Hand
         JSScript *script = fun->getOrCreateScript(cx);
         if (!script)
             MOZ_CRASH();
         return script;
     }
     return fun->nonLazyScript();
 }
 
-JS_PUBLIC_API(bool)
-JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
-                    const char *name, unsigned nargs, const char *const *argnames,
-                    SourceBufferHolder &srcBuf, MutableHandleFunction fun,
-                    HandleObject enclosingStaticScope)
+/*
+ * enclosingStaticScope is a static enclosing scope, if any (e.g. a
+ * StaticWithObject).  If the enclosing scope is the global scope, this must be
+ * null.
+ *
+ * enclosingDynamicScope is a dynamic scope to use, if it's not the global.
+ *
+ * The function will be defined as a property on objToDefineOn if the caller
+ * requested that.
+ */
+static bool
+CompileFunction(JSContext *cx, HandleObject objToDefineOn, const ReadOnlyCompileOptions &options,
+                const char *name, unsigned nargs, const char *const *argnames,
+                SourceBufferHolder &srcBuf,
+                HandleObject enclosingDynamicScope,
+                HandleObject enclosingStaticScope,
+                MutableHandleFunction fun)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj);
+    assertSameCompartment(cx, objToDefineOn);
+    assertSameCompartment(cx, enclosingDynamicScope);
+    assertSameCompartment(cx, enclosingStaticScope);
     RootedAtom funAtom(cx);
     AutoLastFrameCheck lfc(cx);
 
     if (name) {
         funAtom = Atomize(cx, name, strlen(name));
         if (!funAtom)
             return false;
     }
 
     AutoNameVector formals(cx);
     for (unsigned i = 0; i < nargs; i++) {
         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
         if (!argAtom || !formals.append(argAtom->asPropertyName()))
             return false;
     }
 
-    fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
+    fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, enclosingDynamicScope,
                         funAtom, JSFunction::FinalizeKind, TenuredObject));
     if (!fun)
         return false;
 
     if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf,
                                        enclosingStaticScope))
         return false;
 
-    if (obj && funAtom && options.defineOnScope) {
+    if (objToDefineOn && funAtom && options.defineOnScope) {
         Rooted<jsid> id(cx, AtomToId(funAtom));
         RootedValue value(cx, ObjectValue(*fun));
-        if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
+        if (!JSObject::defineGeneric(cx, objToDefineOn, id, value, nullptr,
+                                     nullptr, JSPROP_ENUMERATE))
             return false;
     }
 
     return true;
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
-                    const char16_t *chars, size_t length, MutableHandleFunction fun,
-                    HandleObject enclosingStaticScope)
+                    SourceBufferHolder &srcBuf, MutableHandleFunction fun)
+{
+    return CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf,
+                           obj, NullPtr(), fun);
+}
+
+JS_PUBLIC_API(bool)
+JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
+                    const char *name, unsigned nargs, const char *const *argnames,
+                    const char16_t *chars, size_t length, MutableHandleFunction fun)
 {
     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
-    return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf,
-                               fun, enclosingStaticScope);
+    return JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
                     const char *bytes, size_t length, MutableHandleFunction fun)
 {
     mozilla::UniquePtr<char16_t, JS::FreePolicy> chars;
@@ -4658,37 +4680,66 @@ JS::CompileFunction(JSContext *cx, Handl
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars.get(), length, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
                     const ReadOnlyCompileOptions &options,
                     const char *name, unsigned nargs, const char *const *argnames,
-                    const char16_t *chars, size_t length, MutableHandleFunction fun)
+                    SourceBufferHolder &srcBuf, MutableHandleFunction fun)
 {
     RootedObject dynamicScopeObj(cx);
     RootedObject staticScopeObj(cx);
     if (!CreateScopeObjectsForScopeChain(cx, scopeChain, &dynamicScopeObj, &staticScopeObj))
         return false;
 
-    return JS::CompileFunction(cx, dynamicScopeObj, options, name, nargs,
-                               argnames, chars, length, fun, staticScopeObj);
+    return CompileFunction(cx, /* objToDefineOn = */ JS::NullPtr(), options, name, nargs, argnames,
+                           srcBuf, dynamicScopeObj, staticScopeObj, fun);
+}
+
+JS_PUBLIC_API(bool)
+JS::CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
+                    const ReadOnlyCompileOptions &options,
+                    const char *name, unsigned nargs, const char *const *argnames,
+                    const char16_t *chars, size_t length, MutableHandleFunction fun)
+{
+    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
+    return CompileFunction(cx, scopeChain, options, name, nargs, argnames,
+                           srcBuf, fun);
 }
 
 JS_PUBLIC_API(bool)
 JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                      unsigned nargs, const char *const *argnames,
                      const char16_t *chars, size_t length,
                      const CompileOptions &options, MutableHandleFunction fun)
 {
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length, fun);
 }
 
 JS_PUBLIC_API(bool)
+JS::CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
+                    const ReadOnlyCompileOptions &options,
+                    const char *name, unsigned nargs, const char *const *argnames,
+                    const char *bytes, size_t length, MutableHandleFunction fun)
+{
+    mozilla::UniquePtr<char16_t, JS::FreePolicy> chars;
+    if (options.utf8)
+        chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
+    else
+        chars.reset(InflateString(cx, bytes, &length));
+    if (!chars)
+        return false;
+
+    return CompileFunction(cx, scopeChain, options, name, nargs, argnames,
+                           chars.get(), length, fun);
+}
+
+JS_PUBLIC_API(bool)
 JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name,
                    unsigned nargs, const char *const *argnames,
                    const char *ascii, size_t length,
                    const JS::CompileOptions &options, MutableHandleFunction fun)
 {
     return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length, fun);
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3973,51 +3973,62 @@ CanCompileOffThread(JSContext *cx, const
 extern JS_PUBLIC_API(bool)
 CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
                  const char16_t *chars, size_t length,
                  OffThreadCompileCallback callback, void *callbackData);
 
 extern JS_PUBLIC_API(JSScript *)
 FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token);
 
-/*
- * enclosingStaticScope is a static enclosing scope, if any (e.g. a
- * StaticWithObject).  If the enclosing scope is the global scope, this must be
- * null.
- */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
-                SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun,
-                HandleObject enclosingStaticScope = NullPtr());
+                SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun);
 
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const char *bytes, size_t length, JS::MutableHandleFunction fun);
 
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
-                const char16_t *chars, size_t length, JS::MutableHandleFunction fun,
-                HandleObject enclosingStaticScope = NullPtr());
+                const char16_t *chars, size_t length, JS::MutableHandleFunction fun);
 
 /**
  * Compile a function with scopeChain plus the global as its scope chain.
  * scopeChain must contain objects in the current compartment of cx.  The actual
  * scope chain used for the function will consist of With wrappers for those
  * objects, followed by the current global of the compartment cx is in.  This
  * global must not be explicitly included in the scope chain.
  */
 extern JS_PUBLIC_API(bool)
 CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
                 const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const char16_t *chars, size_t length, JS::MutableHandleFunction fun);
 
+/**
+ * Same as above, but taking a SourceBufferHolder for the function body.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
+                const ReadOnlyCompileOptions &options,
+                const char *name, unsigned nargs, const char *const *argnames,
+                SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun);
+
+/**
+ * Same as above, but taking a const char * for the function body.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext *cx, AutoObjectVector &scopeChain,
+                const ReadOnlyCompileOptions &options,
+                const char *name, unsigned nargs, const char *const *argnames,
+                const char *bytes, size_t length, JS::MutableHandleFunction fun);
+
 } /* namespace JS */
 
 extern JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JS::Handle<JSScript*> script, const char *name, unsigned indent);
 
 /*
  * API extension: OR this into indent to avoid pretty-printing the decompiled
  * source resulting from JS_DecompileFunction{,Body}.