LCOV - code coverage report
Current view: top level - js/src - jsfun.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 711 1209 58.8 %
Date: 2017-07-14 16:53:18 Functions: 47 76 61.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * JS function support.
       9             :  */
      10             : 
      11             : #include "jsfuninlines.h"
      12             : 
      13             : #include "mozilla/ArrayUtils.h"
      14             : #include "mozilla/CheckedInt.h"
      15             : #include "mozilla/Maybe.h"
      16             : #include "mozilla/PodOperations.h"
      17             : #include "mozilla/Range.h"
      18             : 
      19             : #include <string.h>
      20             : 
      21             : #include "jsapi.h"
      22             : #include "jsarray.h"
      23             : #include "jsatom.h"
      24             : #include "jscntxt.h"
      25             : #include "jsobj.h"
      26             : #include "jsscript.h"
      27             : #include "jsstr.h"
      28             : #include "jstypes.h"
      29             : #include "jswrapper.h"
      30             : 
      31             : #include "builtin/Eval.h"
      32             : #include "builtin/Object.h"
      33             : #include "builtin/SelfHostingDefines.h"
      34             : #include "frontend/BytecodeCompiler.h"
      35             : #include "frontend/TokenStream.h"
      36             : #include "gc/Marking.h"
      37             : #include "gc/Policy.h"
      38             : #include "jit/InlinableNatives.h"
      39             : #include "jit/Ion.h"
      40             : #include "jit/JitFrameIterator.h"
      41             : #include "js/CallNonGenericMethod.h"
      42             : #include "js/Proxy.h"
      43             : #include "vm/AsyncFunction.h"
      44             : #include "vm/AsyncIteration.h"
      45             : #include "vm/Debugger.h"
      46             : #include "vm/GlobalObject.h"
      47             : #include "vm/Interpreter.h"
      48             : #include "vm/SelfHosting.h"
      49             : #include "vm/Shape.h"
      50             : #include "vm/SharedImmutableStringsCache.h"
      51             : #include "vm/StringBuffer.h"
      52             : #include "vm/WrapperObject.h"
      53             : #include "vm/Xdr.h"
      54             : 
      55             : #include "jsscriptinlines.h"
      56             : 
      57             : #include "vm/Interpreter-inl.h"
      58             : #include "vm/Stack-inl.h"
      59             : 
      60             : using namespace js;
      61             : using namespace js::gc;
      62             : using namespace js::frontend;
      63             : 
      64             : using mozilla::ArrayLength;
      65             : using mozilla::Maybe;
      66             : using mozilla::PodCopy;
      67             : using mozilla::RangedPtr;
      68             : using mozilla::Some;
      69             : 
      70             : static bool
      71         376 : fun_enumerate(JSContext* cx, HandleObject obj)
      72             : {
      73         376 :     MOZ_ASSERT(obj->is<JSFunction>());
      74             : 
      75         752 :     RootedId id(cx);
      76             :     bool found;
      77             : 
      78         376 :     if (!obj->isBoundFunction() && !obj->as<JSFunction>().isArrow()) {
      79         376 :         id = NameToId(cx->names().prototype);
      80         376 :         if (!HasOwnProperty(cx, obj, id, &found))
      81           0 :             return false;
      82             :     }
      83             : 
      84         376 :     id = NameToId(cx->names().length);
      85         376 :     if (!HasOwnProperty(cx, obj, id, &found))
      86           0 :         return false;
      87             : 
      88         376 :     id = NameToId(cx->names().name);
      89         376 :     if (!HasOwnProperty(cx, obj, id, &found))
      90           0 :         return false;
      91             : 
      92         376 :     return true;
      93             : }
      94             : 
      95             : bool
      96           0 : IsFunction(HandleValue v)
      97             : {
      98           0 :     return v.isObject() && v.toObject().is<JSFunction>();
      99             : }
     100             : 
     101             : static bool
     102           0 : AdvanceToActiveCallLinear(JSContext* cx, NonBuiltinScriptFrameIter& iter, HandleFunction fun)
     103             : {
     104           0 :     MOZ_ASSERT(!fun->isBuiltin());
     105             : 
     106           0 :     for (; !iter.done(); ++iter) {
     107           0 :         if (!iter.isFunctionFrame())
     108           0 :             continue;
     109           0 :         if (iter.matchCallee(cx, fun))
     110           0 :             return true;
     111             :     }
     112           0 :     return false;
     113             : }
     114             : 
     115             : static void
     116           0 : ThrowTypeErrorBehavior(JSContext* cx)
     117             : {
     118             :     JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
     119           0 :                                      JSMSG_THROW_TYPE_ERROR);
     120           0 : }
     121             : 
     122             : static bool
     123           0 : IsFunctionInStrictMode(JSFunction* fun)
     124             : {
     125             :     // Interpreted functions have a strict flag.
     126           0 :     if (fun->isInterpreted() && fun->strict())
     127           0 :         return true;
     128             : 
     129             :     // Only asm.js functions can also be strict.
     130           0 :     return IsAsmJSStrictModeModuleOrFunction(fun);
     131             : }
     132             : 
     133             : static bool
     134           0 : IsNewerTypeFunction(JSFunction* fun) {
     135           0 :     return fun->isArrow() ||
     136           0 :            fun->isStarGenerator() ||
     137           0 :            fun->isLegacyGenerator() ||
     138           0 :            fun->isAsync() ||
     139           0 :            fun->isMethod();
     140             : }
     141             : 
     142             : // Beware: this function can be invoked on *any* function! That includes
     143             : // natives, strict mode functions, bound functions, arrow functions,
     144             : // self-hosted functions and constructors, asm.js functions, functions with
     145             : // destructuring arguments and/or a rest argument, and probably a few more I
     146             : // forgot. Turn back and save yourself while you still can. It's too late for
     147             : // me.
     148             : static bool
     149           0 : ArgumentsRestrictions(JSContext* cx, HandleFunction fun)
     150             : {
     151             :     // Throw if the function is a builtin (note: this doesn't include asm.js),
     152             :     // a strict mode function, or a bound function.
     153             :     // TODO (bug 1057208): ensure semantics are correct for all possible
     154             :     // pairings of callee/caller.
     155           0 :     if (fun->isBuiltin() || IsFunctionInStrictMode(fun) ||
     156           0 :         fun->isBoundFunction() || IsNewerTypeFunction(fun))
     157             :     {
     158           0 :         ThrowTypeErrorBehavior(cx);
     159           0 :         return false;
     160             :     }
     161             : 
     162             :     // Otherwise emit a strict warning about |f.arguments| to discourage use of
     163             :     // this non-standard, performance-harmful feature.
     164           0 :     if (!JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_WARNING | JSREPORT_STRICT, GetErrorMessage,
     165             :                                            nullptr, JSMSG_DEPRECATED_USAGE, js_arguments_str))
     166             :     {
     167           0 :         return false;
     168             :     }
     169             : 
     170           0 :     return true;
     171             : }
     172             : 
     173             : bool
     174           0 : ArgumentsGetterImpl(JSContext* cx, const CallArgs& args)
     175             : {
     176           0 :     MOZ_ASSERT(IsFunction(args.thisv()));
     177             : 
     178           0 :     RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
     179           0 :     if (!ArgumentsRestrictions(cx, fun))
     180           0 :         return false;
     181             : 
     182             :     // Return null if this function wasn't found on the stack.
     183           0 :     NonBuiltinScriptFrameIter iter(cx);
     184           0 :     if (!AdvanceToActiveCallLinear(cx, iter, fun)) {
     185           0 :         args.rval().setNull();
     186           0 :         return true;
     187             :     }
     188             : 
     189           0 :     Rooted<ArgumentsObject*> argsobj(cx, ArgumentsObject::createUnexpected(cx, iter));
     190           0 :     if (!argsobj)
     191           0 :         return false;
     192             : 
     193             :     // Disabling compiling of this script in IonMonkey.  IonMonkey doesn't
     194             :     // guarantee |f.arguments| can be fully recovered, so we try to mitigate
     195             :     // observing this behavior by detecting its use early.
     196           0 :     JSScript* script = iter.script();
     197           0 :     jit::ForbidCompilation(cx, script);
     198             : 
     199           0 :     args.rval().setObject(*argsobj);
     200           0 :     return true;
     201             : }
     202             : 
     203             : static bool
     204           0 : ArgumentsGetter(JSContext* cx, unsigned argc, Value* vp)
     205             : {
     206           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     207           0 :     return CallNonGenericMethod<IsFunction, ArgumentsGetterImpl>(cx, args);
     208             : }
     209             : 
     210             : bool
     211           0 : ArgumentsSetterImpl(JSContext* cx, const CallArgs& args)
     212             : {
     213           0 :     MOZ_ASSERT(IsFunction(args.thisv()));
     214             : 
     215           0 :     RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
     216           0 :     if (!ArgumentsRestrictions(cx, fun))
     217           0 :         return false;
     218             : 
     219             :     // If the function passes the gauntlet, return |undefined|.
     220           0 :     args.rval().setUndefined();
     221           0 :     return true;
     222             : }
     223             : 
     224             : static bool
     225           0 : ArgumentsSetter(JSContext* cx, unsigned argc, Value* vp)
     226             : {
     227           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     228           0 :     return CallNonGenericMethod<IsFunction, ArgumentsSetterImpl>(cx, args);
     229             : }
     230             : 
     231             : // Beware: this function can be invoked on *any* function! That includes
     232             : // natives, strict mode functions, bound functions, arrow functions,
     233             : // self-hosted functions and constructors, asm.js functions, functions with
     234             : // destructuring arguments and/or a rest argument, and probably a few more I
     235             : // forgot. Turn back and save yourself while you still can. It's too late for
     236             : // me.
     237             : static bool
     238           0 : CallerRestrictions(JSContext* cx, HandleFunction fun)
     239             : {
     240             :     // Throw if the function is a builtin (note: this doesn't include asm.js),
     241             :     // a strict mode function, or a bound function.
     242             :     // TODO (bug 1057208): ensure semantics are correct for all possible
     243             :     // pairings of callee/caller.
     244           0 :     if (fun->isBuiltin() || IsFunctionInStrictMode(fun) ||
     245           0 :         fun->isBoundFunction() || IsNewerTypeFunction(fun))
     246             :     {
     247           0 :         ThrowTypeErrorBehavior(cx);
     248           0 :         return false;
     249             :     }
     250             : 
     251             :     // Otherwise emit a strict warning about |f.caller| to discourage use of
     252             :     // this non-standard, performance-harmful feature.
     253           0 :     if (!JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_WARNING | JSREPORT_STRICT, GetErrorMessage,
     254             :                                            nullptr, JSMSG_DEPRECATED_USAGE, js_caller_str))
     255             :     {
     256           0 :         return false;
     257             :     }
     258             : 
     259           0 :     return true;
     260             : }
     261             : 
     262             : bool
     263           0 : CallerGetterImpl(JSContext* cx, const CallArgs& args)
     264             : {
     265           0 :     MOZ_ASSERT(IsFunction(args.thisv()));
     266             : 
     267             :     // Beware!  This function can be invoked on *any* function!  It can't
     268             :     // assume it'll never be invoked on natives, strict mode functions, bound
     269             :     // functions, or anything else that ordinarily has immutable .caller
     270             :     // defined with [[ThrowTypeError]].
     271           0 :     RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
     272           0 :     if (!CallerRestrictions(cx, fun))
     273           0 :         return false;
     274             : 
     275             :     // Also return null if this function wasn't found on the stack.
     276           0 :     NonBuiltinScriptFrameIter iter(cx);
     277           0 :     if (!AdvanceToActiveCallLinear(cx, iter, fun)) {
     278           0 :         args.rval().setNull();
     279           0 :         return true;
     280             :     }
     281             : 
     282           0 :     ++iter;
     283           0 :     while (!iter.done() && iter.isEvalFrame())
     284           0 :         ++iter;
     285             : 
     286           0 :     if (iter.done() || !iter.isFunctionFrame()) {
     287           0 :         args.rval().setNull();
     288           0 :         return true;
     289             :     }
     290             : 
     291           0 :     RootedObject caller(cx, iter.callee(cx));
     292           0 :     if (caller->is<JSFunction>() && caller->as<JSFunction>().isAsync())
     293           0 :         caller = GetWrappedAsyncFunction(&caller->as<JSFunction>());
     294           0 :     if (!cx->compartment()->wrap(cx, &caller))
     295           0 :         return false;
     296             : 
     297             :     // Censor the caller if we don't have full access to it.  If we do, but the
     298             :     // caller is a function with strict mode code, throw a TypeError per ES5.
     299             :     // If we pass these checks, we can return the computed caller.
     300             :     {
     301           0 :         JSObject* callerObj = CheckedUnwrap(caller);
     302           0 :         if (!callerObj) {
     303           0 :             args.rval().setNull();
     304           0 :             return true;
     305             :         }
     306             : 
     307           0 :         JSFunction* callerFun = &callerObj->as<JSFunction>();
     308           0 :         if (IsWrappedAsyncFunction(callerFun))
     309           0 :             callerFun = GetUnwrappedAsyncFunction(callerFun);
     310           0 :         else if (IsWrappedAsyncGenerator(callerFun))
     311           0 :             callerFun = GetUnwrappedAsyncGenerator(callerFun);
     312           0 :         MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
     313             : 
     314           0 :         if (callerFun->strict()) {
     315             :             JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
     316           0 :                                               JSMSG_CALLER_IS_STRICT);
     317           0 :             return false;
     318             :         }
     319             :     }
     320             : 
     321           0 :     args.rval().setObject(*caller);
     322           0 :     return true;
     323             : }
     324             : 
     325             : static bool
     326           0 : CallerGetter(JSContext* cx, unsigned argc, Value* vp)
     327             : {
     328           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     329           0 :     return CallNonGenericMethod<IsFunction, CallerGetterImpl>(cx, args);
     330             : }
     331             : 
     332             : bool
     333           0 : CallerSetterImpl(JSContext* cx, const CallArgs& args)
     334             : {
     335           0 :     MOZ_ASSERT(IsFunction(args.thisv()));
     336             : 
     337             :     // Beware!  This function can be invoked on *any* function!  It can't
     338             :     // assume it'll never be invoked on natives, strict mode functions, bound
     339             :     // functions, or anything else that ordinarily has immutable .caller
     340             :     // defined with [[ThrowTypeError]].
     341           0 :     RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
     342           0 :     if (!CallerRestrictions(cx, fun))
     343           0 :         return false;
     344             : 
     345             :     // Return |undefined| unless an error must be thrown.
     346           0 :     args.rval().setUndefined();
     347             : 
     348             :     // We can almost just return |undefined| here -- but if the caller function
     349             :     // was strict mode code, we still have to throw a TypeError.  This requires
     350             :     // computing the caller, checking that no security boundaries are crossed,
     351             :     // and throwing a TypeError if the resulting caller is strict.
     352             : 
     353           0 :     NonBuiltinScriptFrameIter iter(cx);
     354           0 :     if (!AdvanceToActiveCallLinear(cx, iter, fun))
     355           0 :         return true;
     356             : 
     357           0 :     ++iter;
     358           0 :     while (!iter.done() && iter.isEvalFrame())
     359           0 :         ++iter;
     360             : 
     361           0 :     if (iter.done() || !iter.isFunctionFrame())
     362           0 :         return true;
     363             : 
     364           0 :     RootedObject caller(cx, iter.callee(cx));
     365             :     // |caller| is only used for security access-checking and for its
     366             :     // strictness.  An unwrapped async function has its wrapped async
     367             :     // function's security access and strictness, so don't bother calling
     368             :     // |GetUnwrappedAsyncFunction|.
     369           0 :     if (!cx->compartment()->wrap(cx, &caller)) {
     370           0 :         cx->clearPendingException();
     371           0 :         return true;
     372             :     }
     373             : 
     374             :     // If we don't have full access to the caller, or the caller is not strict,
     375             :     // return undefined.  Otherwise throw a TypeError.
     376           0 :     JSObject* callerObj = CheckedUnwrap(caller);
     377           0 :     if (!callerObj)
     378           0 :         return true;
     379             : 
     380           0 :     JSFunction* callerFun = &callerObj->as<JSFunction>();
     381           0 :     MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
     382             : 
     383           0 :     if (callerFun->strict()) {
     384             :         JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
     385           0 :                                           JSMSG_CALLER_IS_STRICT);
     386           0 :         return false;
     387             :     }
     388             : 
     389           0 :     return true;
     390             : }
     391             : 
     392             : static bool
     393           0 : CallerSetter(JSContext* cx, unsigned argc, Value* vp)
     394             : {
     395           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     396           0 :     return CallNonGenericMethod<IsFunction, CallerSetterImpl>(cx, args);
     397             : }
     398             : 
     399             : static const JSPropertySpec function_properties[] = {
     400             :     JS_PSGS("arguments", ArgumentsGetter, ArgumentsSetter, 0),
     401             :     JS_PSGS("caller", CallerGetter, CallerSetter, 0),
     402             :     JS_PS_END
     403             : };
     404             : 
     405             : static bool
     406         449 : ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id)
     407             : {
     408         449 :     bool isAsyncGenerator = IsWrappedAsyncGenerator(fun);
     409             : 
     410         449 :     MOZ_ASSERT_IF(!isAsyncGenerator, fun->isInterpreted() || fun->isAsmJSNative());
     411         449 :     MOZ_ASSERT(id == NameToId(cx->names().prototype));
     412             : 
     413             :     // Assert that fun is not a compiler-created function object, which
     414             :     // must never leak to script or embedding code and then be mutated.
     415             :     // Also assert that fun is not bound, per the ES5 15.3.4.5 ref above.
     416         449 :     MOZ_ASSERT_IF(!isAsyncGenerator, !IsInternalFunctionObject(*fun));
     417         449 :     MOZ_ASSERT(!fun->isBoundFunction());
     418             : 
     419             :     // Make the prototype object an instance of Object with the same parent as
     420             :     // the function object itself, unless the function is an ES6 generator.  In
     421             :     // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
     422             :     // the GeneratorObjectPrototype singleton.
     423         449 :     bool isStarGenerator = fun->isStarGenerator();
     424         898 :     Rooted<GlobalObject*> global(cx, &fun->global());
     425         898 :     RootedObject objProto(cx);
     426         449 :     if (isAsyncGenerator)
     427           0 :         objProto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, global);
     428         449 :     else if (isStarGenerator)
     429           8 :         objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
     430             :     else
     431         441 :         objProto = GlobalObject::getOrCreateObjectPrototype(cx, global);
     432         449 :     if (!objProto)
     433           0 :         return false;
     434             : 
     435         898 :     RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, objProto,
     436         898 :                                                                      SingletonObject));
     437         449 :     if (!proto)
     438           0 :         return false;
     439             : 
     440             :     // Per ES5 13.2 the prototype's .constructor property is configurable,
     441             :     // non-enumerable, and writable.  However, per the 15 July 2013 ES6 draft,
     442             :     // section 15.19.3, the .prototype of a generator function does not link
     443             :     // back with a .constructor.
     444         449 :     if (!isStarGenerator && !isAsyncGenerator) {
     445         882 :         RootedValue objVal(cx, ObjectValue(*fun));
     446         441 :         if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0))
     447           0 :             return false;
     448             :     }
     449             : 
     450             :     // Per ES5 15.3.5.2 a user-defined function's .prototype property is
     451             :     // initially non-configurable, non-enumerable, and writable.
     452         898 :     RootedValue protoVal(cx, ObjectValue(*proto));
     453         898 :     return DefineProperty(cx, fun, id, protoVal, nullptr, nullptr,
     454         449 :                           JSPROP_PERMANENT | JSPROP_RESOLVING);
     455             : }
     456             : 
     457             : bool
     458        2599 : JSFunction::needsPrototypeProperty()
     459             : {
     460             :     /*
     461             :      * Built-in functions do not have a .prototype property per ECMA-262,
     462             :      * or (Object.prototype, Function.prototype, etc.) have that property
     463             :      * created eagerly.
     464             :      *
     465             :      * ES5 15.3.4.5: bound functions don't have a prototype property. The
     466             :      * isBuiltin() test covers this case because bound functions are native
     467             :      * (and thus built-in) functions by definition/construction.
     468             :      *
     469             :      * ES6 9.2.8 MakeConstructor defines the .prototype property on constructors.
     470             :      * Generators are not constructors, but they have a .prototype property anyway,
     471             :      * according to errata to ES6. See bug 1191486.
     472             :      *
     473             :      * Thus all of the following don't get a .prototype property:
     474             :      * - Methods (that are not class-constructors or generators)
     475             :      * - Arrow functions
     476             :      * - Function.prototype
     477             :      */
     478        2599 :     if (isBuiltin())
     479        2142 :         return IsWrappedAsyncGenerator(this);
     480             : 
     481         457 :     return isConstructor() || isStarGenerator() || isLegacyGenerator() || isAsync();
     482             : }
     483             : 
     484             : static bool
     485        1470 : fun_mayResolve(const JSAtomState& names, jsid id, JSObject*)
     486             : {
     487        1470 :     if (!JSID_IS_ATOM(id))
     488           8 :         return false;
     489             : 
     490        1462 :     JSAtom* atom = JSID_TO_ATOM(id);
     491        1462 :     return atom == names.prototype || atom == names.length || atom == names.name;
     492             : }
     493             : 
     494             : static bool
     495       25281 : fun_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
     496             : {
     497       25281 :     if (!JSID_IS_ATOM(id))
     498         937 :         return true;
     499             : 
     500       48688 :     RootedFunction fun(cx, &obj->as<JSFunction>());
     501             : 
     502       24344 :     if (JSID_IS_ATOM(id, cx->names().prototype)) {
     503        2594 :         if (!fun->needsPrototypeProperty())
     504        2145 :             return true;
     505             : 
     506         449 :         if (!ResolveInterpretedFunctionPrototype(cx, fun, id))
     507           0 :             return false;
     508             : 
     509         449 :         *resolvedp = true;
     510         449 :         return true;
     511             :     }
     512             : 
     513       21750 :     bool isLength = JSID_IS_ATOM(id, cx->names().length);
     514       21750 :     if (isLength || JSID_IS_ATOM(id, cx->names().name)) {
     515         767 :         MOZ_ASSERT(!IsInternalFunctionObject(*obj));
     516             : 
     517        1534 :         RootedValue v(cx);
     518             : 
     519             :         // Since f.length and f.name are configurable, they could be resolved
     520             :         // and then deleted:
     521             :         //     function f(x) {}
     522             :         //     assertEq(f.length, 1);
     523             :         //     delete f.length;
     524             :         //     assertEq(f.name, "f");
     525             :         //     delete f.name;
     526             :         // Afterwards, asking for f.length or f.name again will cause this
     527             :         // resolve hook to run again. Defining the property again the second
     528             :         // time through would be a bug.
     529             :         //     assertEq(f.length, 0);  // gets Function.prototype.length!
     530             :         //     assertEq(f.name, "");  // gets Function.prototype.name!
     531             :         // We use the RESOLVED_LENGTH and RESOLVED_NAME flags as a hack to prevent this
     532             :         // bug.
     533         767 :         if (isLength) {
     534         371 :             if (fun->hasResolvedLength())
     535           0 :                 return true;
     536             : 
     537         371 :             if (!JSFunction::getUnresolvedLength(cx, fun, &v))
     538           0 :                 return false;
     539             :         } else {
     540         396 :             if (fun->hasResolvedName())
     541          14 :                 return true;
     542             : 
     543         778 :             RootedAtom name(cx);
     544         396 :             if (!JSFunction::getUnresolvedName(cx, fun, &name))
     545           0 :                 return false;
     546             : 
     547             :             // Don't define an own .name property for unnamed functions.
     548         396 :             if (!name)
     549          14 :                 return true;
     550             : 
     551         382 :             v.setString(name);
     552             :         }
     553             : 
     554         753 :         if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr,
     555             :                                   JSPROP_READONLY | JSPROP_RESOLVING))
     556             :         {
     557           0 :             return false;
     558             :         }
     559             : 
     560         753 :         if (isLength)
     561         371 :             fun->setResolvedLength();
     562             :         else
     563         382 :             fun->setResolvedName();
     564             : 
     565         753 :         *resolvedp = true;
     566         753 :         return true;
     567             :     }
     568             : 
     569       20983 :     return true;
     570             : }
     571             : 
     572             : template<XDRMode mode>
     573             : bool
     574       13320 : js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope,
     575             :                            HandleScriptSource sourceObject, MutableHandleFunction objp)
     576             : {
     577             :     enum FirstWordFlag {
     578             :         HasAtom             = 0x1,
     579             :         HasStarGeneratorProto = 0x2,
     580             :         IsLazy              = 0x4,
     581             :         HasSingletonType    = 0x8
     582             :     };
     583             : 
     584             :     /* NB: Keep this in sync with CloneInnerInterpretedFunction. */
     585       26640 :     RootedAtom atom(xdr->cx());
     586       13320 :     uint32_t firstword = 0;        /* bitmask of FirstWordFlag */
     587       13320 :     uint32_t flagsword = 0;        /* word for argument count and fun->flags */
     588             : 
     589       13320 :     JSContext* cx = xdr->cx();
     590       26640 :     RootedFunction fun(cx);
     591       26640 :     RootedScript script(cx);
     592       26640 :     Rooted<LazyScript*> lazy(cx);
     593             : 
     594             :     if (mode == XDR_ENCODE) {
     595        3096 :         fun = objp;
     596        3096 :         if (!fun->isInterpreted())
     597           0 :             return xdr->fail(JS::TranscodeResult_Failure_NotInterpretedFun);
     598             : 
     599        3096 :         if (fun->explicitName() || fun->hasCompileTimeName() || fun->hasGuessedAtom())
     600        2948 :             firstword |= HasAtom;
     601             : 
     602        3096 :         if (fun->isStarGenerator() || fun->isAsync())
     603          99 :             firstword |= HasStarGeneratorProto;
     604             : 
     605        3096 :         if (fun->isInterpretedLazy()) {
     606             :             // Encode a lazy script.
     607         285 :             firstword |= IsLazy;
     608         285 :             lazy = fun->lazyScript();
     609             :         } else {
     610             :             // Encode the script.
     611        2811 :             script = fun->nonLazyScript();
     612             :         }
     613             : 
     614        3096 :         if (fun->isSingleton())
     615           0 :             firstword |= HasSingletonType;
     616             : 
     617        3096 :         atom = fun->displayAtom();
     618        6192 :         flagsword = (fun->nargs() << 16) |
     619        3096 :                     (fun->flags() & ~JSFunction::NO_XDR_FLAGS);
     620             : 
     621             :         // The environment of any function which is not reused will always be
     622             :         // null, it is later defined when a function is cloned or reused to
     623             :         // mirror the scope chain.
     624        3096 :         MOZ_ASSERT_IF(fun->isSingleton() &&
     625             :                       !((lazy && lazy->hasBeenCloned()) || (script && script->hasBeenCloned())),
     626             :                       fun->environment() == nullptr);
     627             :     }
     628             : 
     629             :     // Everything added below can substituted by the non-lazy-script version of
     630             :     // this function later.
     631       26640 :     js::AutoXDRTree funTree(xdr, xdr->getTreeKey(fun));
     632             : 
     633       13320 :     if (!xdr->codeUint32(&firstword))
     634           0 :         return false;
     635             : 
     636       13320 :     if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
     637           0 :         return false;
     638       13320 :     if (!xdr->codeUint32(&flagsword))
     639           0 :         return false;
     640             : 
     641             :     if (mode == XDR_DECODE) {
     642       20448 :         RootedObject proto(cx);
     643       10224 :         if (firstword & HasStarGeneratorProto) {
     644             :             // If we are off thread, the generator meta-objects have
     645             :             // already been created by js::StartOffThreadParseTask, so
     646             :             // JSContext* will not be necessary.
     647         327 :             JSContext* context = cx->helperThread() ? nullptr : cx;
     648         327 :             proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(context, cx->global());
     649         327 :             if (!proto)
     650           0 :                 return false;
     651             :         }
     652             : 
     653       10224 :         gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
     654       10224 :         if (uint16_t(flagsword) & JSFunction::EXTENDED)
     655        6522 :             allocKind = gc::AllocKind::FUNCTION_EXTENDED;
     656       10224 :         fun = NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
     657             :                                    /* enclosingDynamicScope = */ nullptr, nullptr, proto,
     658             :                                    allocKind, TenuredObject);
     659       10224 :         if (!fun)
     660           0 :             return false;
     661       10224 :         script = nullptr;
     662             :     }
     663             : 
     664       13320 :     if (firstword & IsLazy) {
     665        1511 :         if (!XDRLazyScript(xdr, enclosingScope, sourceObject, fun, &lazy))
     666           0 :             return false;
     667             :     } else {
     668       11809 :         if (!XDRScript(xdr, enclosingScope, sourceObject, fun, &script))
     669           0 :             return false;
     670             :     }
     671             : 
     672             :     if (mode == XDR_DECODE) {
     673       10224 :         fun->setArgCount(flagsword >> 16);
     674       10224 :         fun->setFlags(uint16_t(flagsword));
     675       10224 :         fun->initAtom(atom);
     676       10224 :         if (firstword & IsLazy) {
     677        1226 :             MOZ_ASSERT(fun->lazyScript() == lazy);
     678             :         } else {
     679        8998 :             MOZ_ASSERT(fun->nonLazyScript() == script);
     680        8998 :             MOZ_ASSERT(fun->nargs() == script->numArgs());
     681             :         }
     682             : 
     683       10224 :         bool singleton = firstword & HasSingletonType;
     684       10224 :         if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
     685           0 :             return false;
     686       10224 :         objp.set(fun);
     687             :     }
     688             : 
     689       13320 :     return true;
     690             : }
     691             : 
     692             : template bool
     693             : js::XDRInterpretedFunction(XDRState<XDR_ENCODE>*, HandleScope, HandleScriptSource,
     694             :                            MutableHandleFunction);
     695             : 
     696             : template bool
     697             : js::XDRInterpretedFunction(XDRState<XDR_DECODE>*, HandleScope, HandleScriptSource,
     698             :                            MutableHandleFunction);
     699             : 
     700             : /* ES6 (04-25-16) 19.2.3.6 Function.prototype [ @@hasInstance ] */
     701             : bool
     702          70 : js::fun_symbolHasInstance(JSContext* cx, unsigned argc, Value* vp)
     703             : {
     704          70 :     CallArgs args = CallArgsFromVp(argc, vp);
     705             : 
     706          70 :     if (args.length() < 1) {
     707           0 :         args.rval().setBoolean(false);
     708           0 :         return true;
     709             :     }
     710             : 
     711             :     /* Step 1. */
     712          70 :     HandleValue func = args.thisv();
     713             : 
     714             :     // Primitives are non-callable and will always return false from
     715             :     // OrdinaryHasInstance.
     716          70 :     if (!func.isObject()) {
     717           0 :         args.rval().setBoolean(false);
     718           0 :         return true;
     719             :     }
     720             : 
     721         140 :     RootedObject obj(cx, &func.toObject());
     722             : 
     723             :     /* Step 2. */
     724             :     bool result;
     725          70 :     if (!OrdinaryHasInstance(cx, obj, args[0], &result))
     726           0 :         return false;
     727             : 
     728          70 :     args.rval().setBoolean(result);
     729          70 :     return true;
     730             : }
     731             : 
     732             : /*
     733             :  * ES6 (4-25-16) 7.3.19 OrdinaryHasInstance
     734             :  */
     735             : bool
     736          72 : JS::OrdinaryHasInstance(JSContext* cx, HandleObject objArg, HandleValue v, bool* bp)
     737             : {
     738          72 :     AssertHeapIsIdle();
     739          72 :     assertSameCompartment(cx, objArg, v);
     740             : 
     741         144 :     RootedObject obj(cx, objArg);
     742             : 
     743             :     /* Step 1. */
     744          72 :     if (!obj->isCallable()) {
     745           0 :         *bp = false;
     746           0 :         return true;
     747             :     }
     748             : 
     749             :     /* Step 2. */
     750          72 :     if (obj->is<JSFunction>() && obj->isBoundFunction()) {
     751             :         /* Steps 2a-b. */
     752           0 :         obj = obj->as<JSFunction>().getBoundFunctionTarget();
     753           0 :         return InstanceOfOperator(cx, obj, v, bp);
     754             :     }
     755             : 
     756             :     /* Step 3. */
     757          72 :     if (!v.isObject()) {
     758          10 :         *bp = false;
     759          10 :         return true;
     760             :     }
     761             : 
     762             :     /* Step 4. */
     763         124 :     RootedValue pval(cx);
     764          62 :     if (!GetProperty(cx, obj, obj, cx->names().prototype, &pval))
     765           0 :         return false;
     766             : 
     767             :     /* Step 5. */
     768          62 :     if (pval.isPrimitive()) {
     769             :         /*
     770             :          * Throw a runtime error if instanceof is called on a function that
     771             :          * has a non-object as its .prototype value.
     772             :          */
     773           0 :         RootedValue val(cx, ObjectValue(*obj));
     774           0 :         ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, val, nullptr);
     775           0 :         return false;
     776             :     }
     777             : 
     778             :     /* Step 6. */
     779         124 :     RootedObject pobj(cx, &pval.toObject());
     780             :     bool isDelegate;
     781          62 :     if (!IsDelegate(cx, pobj, v, &isDelegate))
     782           0 :         return false;
     783          62 :     *bp = isDelegate;
     784          62 :     return true;
     785             : }
     786             : 
     787             : inline void
     788       12788 : JSFunction::trace(JSTracer* trc)
     789             : {
     790       12788 :     if (isExtended()) {
     791        6757 :         TraceRange(trc, ArrayLength(toExtended()->extendedSlots),
     792       13514 :                    (GCPtrValue*)toExtended()->extendedSlots, "nativeReserved");
     793             :     }
     794             : 
     795       12788 :     TraceNullableEdge(trc, &atom_, "atom");
     796             : 
     797       12788 :     if (isInterpreted()) {
     798             :         // Functions can be be marked as interpreted despite having no script
     799             :         // yet at some points when parsing, and can be lazy with no lazy script
     800             :         // for self-hosted code.
     801       11758 :         if (hasScript() && !hasUncompiledScript())
     802       10767 :             TraceManuallyBarrieredEdge(trc, &u.i.s.script_, "script");
     803         991 :         else if (isInterpretedLazy() && u.i.s.lazy_)
     804         661 :             TraceManuallyBarrieredEdge(trc, &u.i.s.lazy_, "lazyScript");
     805             : 
     806       11758 :         if (u.i.env_)
     807       11479 :             TraceManuallyBarrieredEdge(trc, &u.i.env_, "fun_environment");
     808             :     }
     809       12788 : }
     810             : 
     811             : static void
     812       12788 : fun_trace(JSTracer* trc, JSObject* obj)
     813             : {
     814       12788 :     obj->as<JSFunction>().trace(trc);
     815       12788 : }
     816             : 
     817             : static bool
     818           0 : ThrowTypeError(JSContext* cx, unsigned argc, Value* vp)
     819             : {
     820           0 :     ThrowTypeErrorBehavior(cx);
     821           0 :     return false;
     822             : }
     823             : 
     824             : static JSObject*
     825         311 : CreateFunctionConstructor(JSContext* cx, JSProtoKey key)
     826             : {
     827         622 :     Rooted<GlobalObject*> global(cx, cx->global());
     828         622 :     RootedObject functionProto(cx, &global->getPrototype(JSProto_Function).toObject());
     829             : 
     830             :     RootedObject functionCtor(cx,
     831         933 :       NewFunctionWithProto(cx, Function, 1, JSFunction::NATIVE_CTOR,
     832         311 :                            nullptr, HandlePropertyName(cx->names().Function),
     833         622 :                            functionProto, AllocKind::FUNCTION, SingletonObject));
     834         311 :     if (!functionCtor)
     835           0 :         return nullptr;
     836             : 
     837         311 :     return functionCtor;
     838             : 
     839             : }
     840             : 
     841             : static JSObject*
     842         311 : CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
     843             : {
     844         622 :     Rooted<GlobalObject*> self(cx, cx->global());
     845             : 
     846         622 :     RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
     847             :     /*
     848             :      * Bizarrely, |Function.prototype| must be an interpreted function, so
     849             :      * give it the guts to be one.
     850             :      */
     851         622 :     RootedObject enclosingEnv(cx, &self->lexicalEnvironment());
     852             :     JSObject* functionProto_ =
     853         622 :         NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
     854             :                              enclosingEnv, nullptr, objectProto, AllocKind::FUNCTION,
     855         311 :                              SingletonObject);
     856         311 :     if (!functionProto_)
     857           0 :         return nullptr;
     858             : 
     859         622 :     RootedFunction functionProto(cx, &functionProto_->as<JSFunction>());
     860             : 
     861         311 :     const char* rawSource = "function () {\n}";
     862         311 :     size_t sourceLen = strlen(rawSource);
     863         311 :     size_t begin = 9;
     864         311 :     MOZ_ASSERT(rawSource[begin] == '(');
     865         622 :     mozilla::UniquePtr<char16_t[], JS::FreePolicy> source(InflateString(cx, rawSource, &sourceLen));
     866         311 :     if (!source)
     867           0 :         return nullptr;
     868             : 
     869         311 :     ScriptSource* ss = cx->new_<ScriptSource>();
     870         311 :     if (!ss)
     871           0 :         return nullptr;
     872         622 :     ScriptSourceHolder ssHolder(ss);
     873         311 :     if (!ss->setSource(cx, mozilla::Move(source), sourceLen))
     874           0 :         return nullptr;
     875             : 
     876         622 :     CompileOptions options(cx);
     877         311 :     options.setIntroductionType("Function.prototype")
     878         311 :            .setNoScriptRval(true)
     879         311 :            .setVersion(JSVERSION_DEFAULT);
     880         311 :     if (!ss->initFromOptions(cx, options))
     881           0 :         return nullptr;
     882         622 :     RootedScriptSource sourceObject(cx, ScriptSourceObject::create(cx, ss));
     883         311 :     if (!sourceObject || !ScriptSourceObject::initFromOptions(cx, sourceObject, options))
     884           0 :         return nullptr;
     885             : 
     886         933 :     RootedScript script(cx, JSScript::Create(cx,
     887             :                                              options,
     888             :                                              sourceObject,
     889             :                                              begin,
     890         311 :                                              ss->length(),
     891             :                                              0,
     892         933 :                                              ss->length()));
     893         311 :     if (!script || !JSScript::initFunctionPrototype(cx, script, functionProto))
     894           0 :         return nullptr;
     895             : 
     896         311 :     functionProto->initScript(script);
     897         311 :     ObjectGroup* protoGroup = JSObject::getGroup(cx, functionProto);
     898         311 :     if (!protoGroup)
     899           0 :         return nullptr;
     900             : 
     901         311 :     protoGroup->setInterpretedFunction(functionProto);
     902             : 
     903             :     /*
     904             :      * The default 'new' group of Function.prototype is required by type
     905             :      * inference to have unknown properties, to simplify handling of e.g.
     906             :      * NewFunctionClone.
     907             :      */
     908         311 :     if (!JSObject::setNewGroupUnknown(cx, &JSFunction::class_, functionProto))
     909           0 :         return nullptr;
     910             : 
     911             :     // Set the prototype before we call NewFunctionWithProto below. This
     912             :     // ensures EmptyShape::getInitialShape can share function shapes.
     913         311 :     self->setPrototype(key, ObjectValue(*functionProto));
     914             : 
     915             :     // Construct the unique [[%ThrowTypeError%]] function object, used only for
     916             :     // "callee" and "caller" accessors on strict mode arguments objects.  (The
     917             :     // spec also uses this for "arguments" and "caller" on various functions,
     918             :     // but we're experimenting with implementing them using accessors on
     919             :     // |Function.prototype| right now.)
     920             :     //
     921             :     // Note that we can't use NewFunction here, even though we want the normal
     922             :     // Function.prototype for our proto, because we're still in the middle of
     923             :     // creating that as far as the world is concerned, so things will get all
     924             :     // confused.
     925             :     RootedFunction throwTypeError(cx,
     926         622 :       NewFunctionWithProto(cx, ThrowTypeError, 0, JSFunction::NATIVE_FUN,
     927             :                            nullptr, nullptr, functionProto, AllocKind::FUNCTION,
     928         622 :                            SingletonObject));
     929         311 :     if (!throwTypeError || !PreventExtensions(cx, throwTypeError))
     930           0 :         return nullptr;
     931             : 
     932             :     // The "length" property of %ThrowTypeError% is non-configurable, adjust
     933             :     // the default property attributes accordingly.
     934         622 :     Rooted<PropertyDescriptor> nonConfigurableDesc(cx);
     935             :     nonConfigurableDesc.setAttributes(JSPROP_PERMANENT | JSPROP_IGNORE_READONLY |
     936         311 :                                       JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_VALUE);
     937             : 
     938         622 :     RootedId lengthId(cx, NameToId(cx->names().length));
     939         311 :     ObjectOpResult lengthResult;
     940         311 :     if (!NativeDefineProperty(cx, throwTypeError, lengthId, nonConfigurableDesc, lengthResult))
     941           0 :         return nullptr;
     942         311 :     MOZ_ASSERT(lengthResult);
     943             : 
     944             :     // Non-standard: Also change "name" to non-configurable. ECMAScript defines
     945             :     // %ThrowTypeError% as an anonymous function, i.e. it shouldn't actually
     946             :     // get an own "name" property. To be consistent with other built-in,
     947             :     // anonymous functions, we don't delete %ThrowTypeError%'s "name" property.
     948         622 :     RootedId nameId(cx, NameToId(cx->names().name));
     949         311 :     ObjectOpResult nameResult;
     950         311 :     if (!NativeDefineProperty(cx, throwTypeError, nameId, nonConfigurableDesc, nameResult))
     951           0 :         return nullptr;
     952         311 :     MOZ_ASSERT(nameResult);
     953             : 
     954         311 :     self->setThrowTypeError(throwTypeError);
     955             : 
     956         311 :     return functionProto;
     957             : }
     958             : 
     959             : static const ClassOps JSFunctionClassOps = {
     960             :     nullptr,                 /* addProperty */
     961             :     nullptr,                 /* delProperty */
     962             :     nullptr,                 /* getProperty */
     963             :     nullptr,                 /* setProperty */
     964             :     fun_enumerate,
     965             :     nullptr,                 /* newEnumerate */
     966             :     fun_resolve,
     967             :     fun_mayResolve,
     968             :     nullptr,                 /* finalize    */
     969             :     nullptr,                 /* call        */
     970             :     nullptr,
     971             :     nullptr,                 /* construct   */
     972             :     fun_trace,
     973             : };
     974             : 
     975             : static const ClassSpec JSFunctionClassSpec = {
     976             :     CreateFunctionConstructor,
     977             :     CreateFunctionPrototype,
     978             :     nullptr,
     979             :     nullptr,
     980             :     function_methods,
     981             :     function_properties
     982             : };
     983             : 
     984             : const Class JSFunction::class_ = {
     985             :     js_Function_str,
     986             :     JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
     987             :     &JSFunctionClassOps,
     988             :     &JSFunctionClassSpec
     989             : };
     990             : 
     991             : const Class* const js::FunctionClassPtr = &JSFunction::class_;
     992             : 
     993             : JSString*
     994           4 : js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
     995             : {
     996           4 :     if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
     997           0 :         return nullptr;
     998             : 
     999           4 :     if (IsAsmJSModule(fun))
    1000           0 :         return AsmJSModuleToString(cx, fun, !prettyPrint);
    1001           4 :     if (IsAsmJSFunction(fun))
    1002           0 :         return AsmJSFunctionToString(cx, fun);
    1003             : 
    1004           4 :     if (IsWrappedAsyncFunction(fun)) {
    1005           0 :         RootedFunction unwrapped(cx, GetUnwrappedAsyncFunction(fun));
    1006           0 :         return FunctionToString(cx, unwrapped, prettyPrint);
    1007             :     }
    1008           4 :     if (IsWrappedAsyncGenerator(fun)) {
    1009           0 :         RootedFunction unwrapped(cx, GetUnwrappedAsyncGenerator(fun));
    1010           0 :         return FunctionToString(cx, unwrapped, prettyPrint);
    1011             :     }
    1012             : 
    1013           8 :     StringBuffer out(cx);
    1014           8 :     RootedScript script(cx);
    1015             : 
    1016           4 :     if (fun->hasScript()) {
    1017           1 :         script = fun->nonLazyScript();
    1018           1 :         if (script->isGeneratorExp()) {
    1019           0 :             if (!out.append("function genexp() {") ||
    1020           0 :                 !out.append("\n    [generator expression]\n") ||
    1021           0 :                 !out.append("}"))
    1022             :             {
    1023           0 :                 return nullptr;
    1024             :             }
    1025           0 :             return out.finishString();
    1026             :         }
    1027             :     }
    1028             : 
    1029           4 :     bool funIsNonArrowLambda = fun->isLambda() && !fun->isArrow();
    1030             : 
    1031             :     // Default class constructors are self-hosted, but have their source
    1032             :     // objects overridden to refer to the span of the class statement or
    1033             :     // expression. Non-default class constructors are never self-hosted. So,
    1034             :     // all class constructors always have source.
    1035           5 :     bool haveSource = fun->isInterpreted() && (fun->isClassConstructor() ||
    1036           5 :                                                !fun->isSelfHostedBuiltin());
    1037             : 
    1038             :     // If we're not in pretty mode, put parentheses around lambda functions
    1039             :     // so that eval returns lambda, not function statement.
    1040           4 :     if (haveSource && !prettyPrint && funIsNonArrowLambda) {
    1041           0 :         if (!out.append("("))
    1042           0 :             return nullptr;
    1043             :     }
    1044             : 
    1045           5 :     if (haveSource && !script->scriptSource()->hasSourceData() &&
    1046           1 :         !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
    1047             :     {
    1048           0 :         return nullptr;
    1049             :     }
    1050             : 
    1051          27 :     auto AppendPrelude = [cx, &out, &fun]() {
    1052           3 :         if (fun->isAsync()) {
    1053           0 :             if (!out.append("async "))
    1054           0 :                 return false;
    1055             :         }
    1056             : 
    1057           3 :         if (!fun->isArrow()) {
    1058           3 :             if (!out.append("function"))
    1059           0 :                 return false;
    1060             : 
    1061           3 :             if (fun->isStarGenerator()) {
    1062           0 :                 if (!out.append('*'))
    1063           0 :                     return false;
    1064             :             }
    1065             :         }
    1066             : 
    1067           3 :         if (fun->explicitName()) {
    1068           3 :             if (!out.append(' '))
    1069           0 :                 return false;
    1070           3 :             if (fun->isBoundFunction() && !fun->hasBoundFunctionNamePrefix()) {
    1071           0 :                 if (!out.append(cx->names().boundWithSpace))
    1072           0 :                     return false;
    1073             :             }
    1074           6 :             if (!out.append(fun->explicitName()))
    1075           0 :                 return false;
    1076             :         }
    1077           3 :         return true;
    1078           4 :     };
    1079             : 
    1080           4 :     if (haveSource) {
    1081           1 :         if (!script->appendSourceDataForToString(cx, out))
    1082           0 :             return nullptr;
    1083             : 
    1084           1 :         if (!prettyPrint && funIsNonArrowLambda) {
    1085           0 :             if (!out.append(")"))
    1086           0 :                 return nullptr;
    1087             :         }
    1088           3 :     } else if (fun->isInterpreted() &&
    1089           0 :                (!fun->isSelfHostedBuiltin() ||
    1090           0 :                 fun->infallibleIsDefaultClassConstructor(cx)))
    1091             :     {
    1092             :         // Default class constructors should always haveSource except;
    1093             :         //
    1094             :         // 1. Source has been discarded for the whole compartment.
    1095             :         //
    1096             :         // 2. The source is marked as "lazy", i.e., retrieved on demand, and
    1097             :         // the embedding has not provided a hook to retrieve sources.
    1098           0 :         MOZ_ASSERT_IF(fun->infallibleIsDefaultClassConstructor(cx),
    1099             :                       !cx->runtime()->sourceHook.ref() ||
    1100             :                       !script->scriptSource()->sourceRetrievable() ||
    1101             :                       fun->compartment()->behaviors().discardSource());
    1102             : 
    1103           0 :         if (!AppendPrelude() ||
    1104           0 :             !out.append("() {\n    ") ||
    1105           0 :             !out.append("[sourceless code]") ||
    1106           0 :             !out.append("\n}"))
    1107             :         {
    1108           0 :             return nullptr;
    1109             :         }
    1110             :     } else {
    1111           6 :         if (!AppendPrelude() ||
    1112           3 :             !out.append("() {\n    "))
    1113           0 :             return nullptr;
    1114             : 
    1115           3 :         if (!out.append("[native code]"))
    1116           0 :             return nullptr;
    1117             : 
    1118           3 :         if (!out.append("\n}"))
    1119           0 :             return nullptr;
    1120             :     }
    1121           4 :     return out.finishString();
    1122             : }
    1123             : 
    1124             : JSString*
    1125           4 : fun_toStringHelper(JSContext* cx, HandleObject obj, unsigned indent)
    1126             : {
    1127           4 :     if (!obj->is<JSFunction>()) {
    1128           0 :         if (JSFunToStringOp op = obj->getOpsFunToString())
    1129           0 :             return op(cx, obj, indent);
    1130             : 
    1131             :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    1132             :                                   JSMSG_INCOMPATIBLE_PROTO,
    1133           0 :                                   js_Function_str, js_toString_str, "object");
    1134           0 :         return nullptr;
    1135             :     }
    1136             : 
    1137           8 :     RootedFunction fun(cx, &obj->as<JSFunction>());
    1138           4 :     return FunctionToString(cx, fun, indent != JS_DONT_PRETTY_PRINT);
    1139             : }
    1140             : 
    1141             : bool
    1142           3 : js::FunctionHasDefaultHasInstance(JSFunction* fun, const WellKnownSymbols& symbols)
    1143             : {
    1144           3 :     jsid id = SYMBOL_TO_JSID(symbols.hasInstance);
    1145           3 :     Shape* shape = fun->lookupPure(id);
    1146           3 :     if (shape) {
    1147           0 :         if (!shape->hasSlot() || !shape->hasDefaultGetter())
    1148           0 :             return false;
    1149           0 :         const Value hasInstance = fun->as<NativeObject>().getSlot(shape->slot());
    1150           0 :         return IsNativeFunction(hasInstance, js::fun_symbolHasInstance);
    1151             :     }
    1152           3 :     return true;
    1153             : }
    1154             : 
    1155             : bool
    1156           4 : js::fun_toString(JSContext* cx, unsigned argc, Value* vp)
    1157             : {
    1158           4 :     CallArgs args = CallArgsFromVp(argc, vp);
    1159           4 :     MOZ_ASSERT(IsFunctionObject(args.calleev()));
    1160             : 
    1161           4 :     uint32_t indent = 0;
    1162             : 
    1163           4 :     if (args.length() != 0 && !ToUint32(cx, args[0], &indent))
    1164           0 :         return false;
    1165             : 
    1166           8 :     RootedObject obj(cx, ToObject(cx, args.thisv()));
    1167           4 :     if (!obj)
    1168           0 :         return false;
    1169             : 
    1170           8 :     RootedString str(cx, fun_toStringHelper(cx, obj, indent));
    1171           4 :     if (!str)
    1172           0 :         return false;
    1173             : 
    1174           4 :     args.rval().setString(str);
    1175           4 :     return true;
    1176             : }
    1177             : 
    1178             : #if JS_HAS_TOSOURCE
    1179             : static bool
    1180           0 : fun_toSource(JSContext* cx, unsigned argc, Value* vp)
    1181             : {
    1182           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1183           0 :     MOZ_ASSERT(IsFunctionObject(args.calleev()));
    1184             : 
    1185           0 :     RootedObject obj(cx, ToObject(cx, args.thisv()));
    1186           0 :     if (!obj)
    1187           0 :         return false;
    1188             : 
    1189           0 :     RootedString str(cx);
    1190           0 :     if (obj->isCallable())
    1191           0 :         str = fun_toStringHelper(cx, obj, JS_DONT_PRETTY_PRINT);
    1192             :     else
    1193           0 :         str = ObjectToSource(cx, obj);
    1194             : 
    1195           0 :     if (!str)
    1196           0 :         return false;
    1197           0 :     args.rval().setString(str);
    1198           0 :     return true;
    1199             : }
    1200             : #endif
    1201             : 
    1202             : bool
    1203         399 : js::fun_call(JSContext* cx, unsigned argc, Value* vp)
    1204             : {
    1205         399 :     CallArgs args = CallArgsFromVp(argc, vp);
    1206             : 
    1207         399 :     HandleValue func = args.thisv();
    1208             : 
    1209             :     // We don't need to do this -- Call would do it for us -- but the error
    1210             :     // message is *much* better if we do this here.  (Without this,
    1211             :     // JSDVG_SEARCH_STACK tries to decompile |func| as if it were |this| in
    1212             :     // the scripted caller's frame -- so for example
    1213             :     //
    1214             :     //   Function.prototype.call.call({});
    1215             :     //
    1216             :     // would identify |{}| as |this| as being the result of evaluating
    1217             :     // |Function.prototype.call| and would conclude, "Function.prototype.call
    1218             :     // is not a function".  Grotesque.)
    1219         399 :     if (!IsCallable(func)) {
    1220           0 :         ReportIncompatibleMethod(cx, args, &JSFunction::class_);
    1221           0 :         return false;
    1222             :     }
    1223             : 
    1224         399 :     size_t argCount = args.length();
    1225         399 :     if (argCount > 0)
    1226         399 :         argCount--; // strip off provided |this|
    1227             : 
    1228         798 :     InvokeArgs iargs(cx);
    1229         399 :     if (!iargs.init(cx, argCount))
    1230           0 :         return false;
    1231             : 
    1232         503 :     for (size_t i = 0; i < argCount; i++)
    1233         104 :         iargs[i].set(args[i + 1]);
    1234             : 
    1235         399 :     return Call(cx, func, args.get(0), iargs, args.rval());
    1236             : }
    1237             : 
    1238             : // ES5 15.3.4.3
    1239             : bool
    1240         438 : js::fun_apply(JSContext* cx, unsigned argc, Value* vp)
    1241             : {
    1242         438 :     CallArgs args = CallArgsFromVp(argc, vp);
    1243             : 
    1244             :     // Step 1.
    1245             :     //
    1246             :     // Note that we must check callability here, not at actual call time,
    1247             :     // because extracting argument values from the provided arraylike might
    1248             :     // have side effects or throw an exception.
    1249         438 :     HandleValue fval = args.thisv();
    1250         438 :     if (!IsCallable(fval)) {
    1251           0 :         ReportIncompatibleMethod(cx, args, &JSFunction::class_);
    1252           0 :         return false;
    1253             :     }
    1254             : 
    1255             :     // Step 2.
    1256         438 :     if (args.length() < 2 || args[1].isNullOrUndefined())
    1257         333 :         return fun_call(cx, (args.length() > 0) ? 1 : 0, vp);
    1258             : 
    1259         210 :     InvokeArgs args2(cx);
    1260             : 
    1261             :     // A JS_OPTIMIZED_ARGUMENTS magic value means that 'arguments' flows into
    1262             :     // this apply call from a scripted caller and, as an optimization, we've
    1263             :     // avoided creating it since apply can simply pull the argument values from
    1264             :     // the calling frame (which we must do now).
    1265         105 :     if (args[1].isMagic(JS_OPTIMIZED_ARGUMENTS)) {
    1266             :         // Step 3-6.
    1267           0 :         ScriptFrameIter iter(cx);
    1268           0 :         MOZ_ASSERT(iter.numActualArgs() <= ARGS_LENGTH_MAX);
    1269           0 :         if (!args2.init(cx, iter.numActualArgs()))
    1270           0 :             return false;
    1271             : 
    1272             :         // Steps 7-8.
    1273           0 :         iter.unaliasedForEachActual(cx, CopyTo(args2.array()));
    1274             :     } else {
    1275             :         // Step 3.
    1276         105 :         if (!args[1].isObject()) {
    1277             :             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    1278           0 :                                       JSMSG_BAD_APPLY_ARGS, js_apply_str);
    1279           0 :             return false;
    1280             :         }
    1281             : 
    1282             :         // Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in
    1283             :         // original version of ES5).
    1284         210 :         RootedObject aobj(cx, &args[1].toObject());
    1285             :         uint32_t length;
    1286         105 :         if (!GetLengthProperty(cx, aobj, &length))
    1287           0 :             return false;
    1288             : 
    1289             :         // Step 6.
    1290         105 :         if (!args2.init(cx, length))
    1291           0 :             return false;
    1292             : 
    1293         105 :         MOZ_ASSERT(length <= ARGS_LENGTH_MAX);
    1294             : 
    1295             :         // Steps 7-8.
    1296         105 :         if (!GetElements(cx, aobj, length, args2.array()))
    1297           0 :             return false;
    1298             :     }
    1299             : 
    1300             :     // Step 9.
    1301         105 :     return Call(cx, fval, args[0], args2, args.rval());
    1302             : }
    1303             : 
    1304             : bool
    1305           3 : JSFunction::infallibleIsDefaultClassConstructor(JSContext* cx) const
    1306             : {
    1307           3 :     if (!isSelfHostedBuiltin())
    1308           0 :         return false;
    1309             : 
    1310           3 :     bool isDefault = false;
    1311           3 :     if (isInterpretedLazy()) {
    1312           3 :         JSAtom* name = &getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom();
    1313           3 :         isDefault = name == cx->names().DefaultDerivedClassConstructor ||
    1314           0 :                     name == cx->names().DefaultBaseClassConstructor;
    1315             :     } else {
    1316           0 :         isDefault = nonLazyScript()->isDefaultClassConstructor();
    1317             :     }
    1318             : 
    1319           3 :     MOZ_ASSERT_IF(isDefault, isConstructor());
    1320           3 :     MOZ_ASSERT_IF(isDefault, isClassConstructor());
    1321           3 :     return isDefault;
    1322             : }
    1323             : 
    1324             : bool
    1325         462 : JSFunction::isDerivedClassConstructor()
    1326             : {
    1327             :     bool derived;
    1328         462 :     if (isInterpretedLazy()) {
    1329             :         // There is only one plausible lazy self-hosted derived
    1330             :         // constructor.
    1331           0 :         if (isSelfHostedBuiltin()) {
    1332           0 :             JSAtom* name = &getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom();
    1333             : 
    1334             :             // This function is called from places without access to a
    1335             :             // JSContext. Trace some plumbing to get what we want.
    1336           0 :             derived = name == compartment()->runtimeFromAnyThread()->
    1337           0 :                               commonNames->DefaultDerivedClassConstructor;
    1338             :         } else {
    1339           0 :             derived = lazyScript()->isDerivedClassConstructor();
    1340             :         }
    1341             :     } else {
    1342         462 :         derived = nonLazyScript()->isDerivedClassConstructor();
    1343             :     }
    1344         462 :     MOZ_ASSERT_IF(derived, isClassConstructor());
    1345         462 :     return derived;
    1346             : }
    1347             : 
    1348             : /* static */ bool
    1349         957 : JSFunction::getLength(JSContext* cx, HandleFunction fun, uint16_t* length)
    1350             : {
    1351         957 :     MOZ_ASSERT(!fun->isBoundFunction());
    1352         957 :     if (fun->isInterpretedLazy() && !getOrCreateScript(cx, fun))
    1353           0 :         return false;
    1354             : 
    1355         957 :     *length = fun->isNative() ? fun->nargs() : fun->nonLazyScript()->funLength();
    1356         957 :     return true;
    1357             : }
    1358             : 
    1359             : /* static */ bool
    1360         700 : JSFunction::getUnresolvedLength(JSContext* cx, HandleFunction fun, MutableHandleValue v)
    1361             : {
    1362         700 :     MOZ_ASSERT(!IsInternalFunctionObject(*fun));
    1363         700 :     MOZ_ASSERT(!fun->hasResolvedLength());
    1364             : 
    1365             :     // Bound functions' length can have values up to MAX_SAFE_INTEGER, so
    1366             :     // they're handled differently from other functions.
    1367         700 :     if (fun->isBoundFunction()) {
    1368           3 :         MOZ_ASSERT(fun->getExtendedSlot(BOUND_FUN_LENGTH_SLOT).isNumber());
    1369           3 :         v.set(fun->getExtendedSlot(BOUND_FUN_LENGTH_SLOT));
    1370           3 :         return true;
    1371             :     }
    1372             : 
    1373             :     uint16_t length;
    1374         697 :     if (!JSFunction::getLength(cx, fun, &length))
    1375           0 :         return false;
    1376             : 
    1377         697 :     v.setInt32(length);
    1378         697 :     return true;
    1379             : }
    1380             : 
    1381             : /* static */ bool
    1382         725 : JSFunction::getUnresolvedName(JSContext* cx, HandleFunction fun, MutableHandleAtom v)
    1383             : {
    1384         725 :     MOZ_ASSERT(!IsInternalFunctionObject(*fun));
    1385         725 :     MOZ_ASSERT(!fun->hasResolvedName());
    1386             : 
    1387         725 :     JSAtom* name = fun->explicitOrCompileTimeName();
    1388         725 :     if (fun->isClassConstructor()) {
    1389             :         // It's impossible to have an empty named class expression. We use
    1390             :         // empty as a sentinel when creating default class constructors.
    1391          14 :         MOZ_ASSERT(name != cx->names().empty);
    1392             : 
    1393             :         // Unnamed class expressions should not get a .name property at all.
    1394          14 :         if (name)
    1395           0 :             v.set(name);
    1396          14 :         return true;
    1397             :     }
    1398             : 
    1399         711 :     if (fun->isBoundFunction() && !fun->hasBoundFunctionNamePrefix()) {
    1400             :         // Bound functions are never unnamed.
    1401           3 :         MOZ_ASSERT(name);
    1402             : 
    1403           3 :         if (name->length() > 0) {
    1404           2 :             StringBuffer sb(cx);
    1405           1 :             if (!sb.append(cx->names().boundWithSpace) || !sb.append(name))
    1406           0 :                 return false;
    1407             : 
    1408           1 :             name = sb.finishAtom();
    1409           1 :             if (!name)
    1410           0 :                 return false;
    1411             :         } else {
    1412           2 :             name = cx->names().boundWithSpace;
    1413             :         }
    1414             : 
    1415           3 :         fun->setPrefixedBoundFunctionName(name);
    1416             :     }
    1417             : 
    1418         711 :     v.set(name != nullptr ? name : cx->names().empty);
    1419         711 :     return true;
    1420             : }
    1421             : 
    1422             : static const js::Value&
    1423         330 : BoundFunctionEnvironmentSlotValue(const JSFunction* fun, uint32_t slotIndex)
    1424             : {
    1425         330 :     MOZ_ASSERT(fun->isBoundFunction());
    1426         330 :     MOZ_ASSERT(fun->environment()->is<CallObject>());
    1427         330 :     CallObject* callObject = &fun->environment()->as<CallObject>();
    1428         330 :     return callObject->getSlot(slotIndex);
    1429             : }
    1430             : 
    1431             : JSObject*
    1432         330 : JSFunction::getBoundFunctionTarget() const
    1433             : {
    1434         330 :     js::Value targetVal = BoundFunctionEnvironmentSlotValue(this, JSSLOT_BOUND_FUNCTION_TARGET);
    1435         330 :     MOZ_ASSERT(IsCallable(targetVal));
    1436         330 :     return &targetVal.toObject();
    1437             : }
    1438             : 
    1439             : const js::Value&
    1440           0 : JSFunction::getBoundFunctionThis() const
    1441             : {
    1442           0 :     return BoundFunctionEnvironmentSlotValue(this, JSSLOT_BOUND_FUNCTION_THIS);
    1443             : }
    1444             : 
    1445             : static ArrayObject*
    1446           0 : GetBoundFunctionArguments(const JSFunction* boundFun)
    1447             : {
    1448           0 :     js::Value argsVal = BoundFunctionEnvironmentSlotValue(boundFun, JSSLOT_BOUND_FUNCTION_ARGS);
    1449           0 :     return &argsVal.toObject().as<ArrayObject>();
    1450             : }
    1451             : 
    1452             : const js::Value&
    1453           0 : JSFunction::getBoundFunctionArgument(unsigned which) const
    1454             : {
    1455           0 :     MOZ_ASSERT(which < getBoundFunctionArgumentCount());
    1456           0 :     return GetBoundFunctionArguments(this)->getDenseElement(which);
    1457             : }
    1458             : 
    1459             : size_t
    1460           0 : JSFunction::getBoundFunctionArgumentCount() const
    1461             : {
    1462           0 :     return GetBoundFunctionArguments(this)->length();
    1463             : }
    1464             : 
    1465             : /* static */ bool
    1466         330 : JSFunction::finishBoundFunctionInit(JSContext* cx, HandleFunction bound, HandleObject targetObj,
    1467             :                                     int32_t argCount)
    1468             : {
    1469         330 :     bound->setIsBoundFunction();
    1470         330 :     MOZ_ASSERT(bound->getBoundFunctionTarget() == targetObj);
    1471             : 
    1472             :     // 9.4.1.3 BoundFunctionCreate, steps 1, 3-5, 8-12 (Already performed).
    1473             : 
    1474             :     // 9.4.1.3 BoundFunctionCreate, step 6.
    1475         330 :     if (targetObj->isConstructor())
    1476         207 :         bound->setIsConstructor();
    1477             : 
    1478             :     // 9.4.1.3 BoundFunctionCreate, step 2.
    1479         660 :     RootedObject proto(cx);
    1480         330 :     if (!GetPrototype(cx, targetObj, &proto))
    1481           0 :         return false;
    1482             : 
    1483             :     // 9.4.1.3 BoundFunctionCreate, step 7.
    1484         330 :     if (bound->staticPrototype() != proto) {
    1485           6 :         if (!SetPrototype(cx, bound, proto))
    1486           0 :             return false;
    1487             :     }
    1488             : 
    1489         330 :     double length = 0.0;
    1490             : 
    1491             :     // Try to avoid invoking the resolve hook.
    1492         330 :     if (targetObj->is<JSFunction>() && !targetObj->as<JSFunction>().hasResolvedLength()) {
    1493         658 :         RootedValue targetLength(cx);
    1494         329 :         if (!JSFunction::getUnresolvedLength(cx, targetObj.as<JSFunction>(), &targetLength))
    1495           0 :             return false;
    1496             : 
    1497         329 :         length = Max(0.0, targetLength.toNumber() - argCount);
    1498             :     } else {
    1499             :         // 19.2.3.2 Function.prototype.bind, step 5.
    1500             :         bool hasLength;
    1501           2 :         RootedId idRoot(cx, NameToId(cx->names().length));
    1502           1 :         if (!HasOwnProperty(cx, targetObj, idRoot, &hasLength))
    1503           0 :             return false;
    1504             : 
    1505             :         // 19.2.3.2 Function.prototype.bind, step 6.
    1506           1 :         if (hasLength) {
    1507           0 :             RootedValue targetLength(cx);
    1508           0 :             if (!GetProperty(cx, targetObj, targetObj, idRoot, &targetLength))
    1509           0 :                 return false;
    1510             : 
    1511           0 :             if (targetLength.isNumber())
    1512           0 :                 length = Max(0.0, JS::ToInteger(targetLength.toNumber()) - argCount);
    1513             :         }
    1514             : 
    1515             :         // 19.2.3.2 Function.prototype.bind, step 7 (implicit).
    1516             :     }
    1517             : 
    1518             :     // 19.2.3.2 Function.prototype.bind, step 8.
    1519         330 :     bound->setExtendedSlot(BOUND_FUN_LENGTH_SLOT, NumberValue(length));
    1520             : 
    1521             :     // Try to avoid invoking the resolve hook.
    1522         660 :     RootedAtom name(cx);
    1523         330 :     if (targetObj->is<JSFunction>() && !targetObj->as<JSFunction>().hasResolvedName()) {
    1524         329 :         if (!JSFunction::getUnresolvedName(cx, targetObj.as<JSFunction>(), &name))
    1525           0 :             return false;
    1526             :     }
    1527             : 
    1528             :     // 19.2.3.2 Function.prototype.bind, steps 9-11.
    1529         330 :     if (!name) {
    1530             :         // 19.2.3.2 Function.prototype.bind, step 9.
    1531           2 :         RootedValue targetName(cx);
    1532           1 :         if (!GetProperty(cx, targetObj, targetObj, cx->names().name, &targetName))
    1533           0 :             return false;
    1534             : 
    1535             :         // 19.2.3.2 Function.prototype.bind, step 10.
    1536           1 :         if (targetName.isString() && !targetName.toString()->empty()) {
    1537           0 :             name = AtomizeString(cx, targetName.toString());
    1538           0 :             if (!name)
    1539           0 :                 return false;
    1540             :         } else {
    1541           1 :             name = cx->names().empty;
    1542             :         }
    1543             :     }
    1544             : 
    1545         330 :     MOZ_ASSERT(!bound->hasGuessedAtom());
    1546         330 :     bound->setAtom(name);
    1547             : 
    1548         330 :     return true;
    1549             : }
    1550             : 
    1551             : /* static */ bool
    1552        2246 : JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFunction fun)
    1553             : {
    1554        2246 :     MOZ_ASSERT(fun->isInterpretedLazy());
    1555             : 
    1556        4491 :     Rooted<LazyScript*> lazy(cx, fun->lazyScriptOrNull());
    1557        2246 :     if (lazy) {
    1558        3379 :         RootedScript script(cx, lazy->maybeScript());
    1559             : 
    1560             :         // Only functions without inner functions or direct eval are
    1561             :         // re-lazified. Functions with either of those are on the static scope
    1562             :         // chain of their inner functions, or in the case of eval, possibly
    1563             :         // eval'd inner functions. This prohibits re-lazification as
    1564             :         // StaticScopeIter queries needsCallObject of those functions, which
    1565             :         // requires a non-lazy script.  Note that if this ever changes,
    1566             :         // XDRRelazificationInfo will have to be fixed.
    1567        1690 :         bool canRelazify = !lazy->numInnerFunctions() && !lazy->hasDirectEval();
    1568             : 
    1569        1690 :         if (script) {
    1570          25 :             fun->setUnlazifiedScript(script);
    1571             :             // Remember the lazy script on the compiled script, so it can be
    1572             :             // stored on the function again in case of re-lazification.
    1573          25 :             if (canRelazify)
    1574          25 :                 script->setLazyScript(lazy);
    1575          25 :             return true;
    1576             :         }
    1577             : 
    1578        1665 :         if (fun != lazy->functionNonDelazifying()) {
    1579         256 :             if (!LazyScript::functionDelazifying(cx, lazy))
    1580           0 :                 return false;
    1581         256 :             script = lazy->functionNonDelazifying()->nonLazyScript();
    1582         256 :             if (!script)
    1583           0 :                 return false;
    1584             : 
    1585         256 :             fun->setUnlazifiedScript(script);
    1586         256 :             return true;
    1587             :         }
    1588             : 
    1589             :         // Lazy script caching is only supported for leaf functions. If a
    1590             :         // script with inner functions was returned by the cache, those inner
    1591             :         // functions would be delazified when deep cloning the script, even if
    1592             :         // they have never executed.
    1593             :         //
    1594             :         // Additionally, the lazy script cache is not used during incremental
    1595             :         // GCs, to avoid resurrecting dead scripts after incremental sweeping
    1596             :         // has started.
    1597        1409 :         if (canRelazify && !JS::IsIncrementalGCInProgress(cx)) {
    1598        1212 :             LazyScriptCache::Lookup lookup(cx, lazy);
    1599        1212 :             cx->caches().lazyScriptCache.lookup(lookup, script.address());
    1600             :         }
    1601             : 
    1602        1409 :         if (script) {
    1603           0 :             RootedScope enclosingScope(cx, lazy->enclosingScope());
    1604           0 :             RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, enclosingScope, fun, script));
    1605           0 :             if (!clonedScript)
    1606           0 :                 return false;
    1607             : 
    1608           0 :             clonedScript->setSourceObject(lazy->sourceObject());
    1609             : 
    1610           0 :             fun->initAtom(script->functionNonDelazifying()->displayAtom());
    1611             : 
    1612           0 :             if (!lazy->maybeScript())
    1613           0 :                 lazy->initScript(clonedScript);
    1614           0 :             return true;
    1615             :         }
    1616             : 
    1617        1409 :         MOZ_ASSERT(lazy->scriptSource()->hasSourceData());
    1618             : 
    1619             :         // Parse and compile the script from source.
    1620        1409 :         size_t lazyLength = lazy->end() - lazy->begin();
    1621        2817 :         UncompressedSourceCache::AutoHoldEntry holder;
    1622        1409 :         ScriptSource::PinnedChars chars(cx, lazy->scriptSource(), holder,
    1623        4226 :                                         lazy->begin(), lazyLength);
    1624        1409 :         if (!chars.get())
    1625           0 :             return false;
    1626             : 
    1627        1409 :         if (!frontend::CompileLazyFunction(cx, lazy, chars.get(), lazyLength)) {
    1628             :             // The frontend may have linked the function and the non-lazy
    1629             :             // script together during bytecode compilation. Reset it now on
    1630             :             // error.
    1631           0 :             fun->initLazyScript(lazy);
    1632           0 :             if (lazy->hasScript())
    1633           0 :                 lazy->resetScript();
    1634           0 :             return false;
    1635             :         }
    1636             : 
    1637        1408 :         script = fun->nonLazyScript();
    1638             : 
    1639             :         // Remember the compiled script on the lazy script itself, in case
    1640             :         // there are clones of the function still pointing to the lazy script.
    1641        1408 :         if (!lazy->maybeScript())
    1642           0 :             lazy->initScript(script);
    1643             : 
    1644             :         // Try to insert the newly compiled script into the lazy script cache.
    1645        1408 :         if (canRelazify) {
    1646             :             // A script's starting column isn't set by the bytecode emitter, so
    1647             :             // specify this from the lazy script so that if an identical lazy
    1648             :             // script is encountered later a match can be determined.
    1649        1211 :             script->setColumn(lazy->column());
    1650             : 
    1651        1211 :             LazyScriptCache::Lookup lookup(cx, lazy);
    1652        1211 :             cx->caches().lazyScriptCache.insert(lookup, script);
    1653             : 
    1654             :             // Remember the lazy script on the compiled script, so it can be
    1655             :             // stored on the function again in case of re-lazification.
    1656             :             // Only functions without inner functions are re-lazified.
    1657        1211 :             script->setLazyScript(lazy);
    1658             :         }
    1659             : 
    1660             :         // XDR the newly delazified function.
    1661        1408 :         if (script->scriptSource()->hasEncoder()) {
    1662           0 :             RootedScriptSource sourceObject(cx, lazy->sourceObject());
    1663           0 :             if (!script->scriptSource()->xdrEncodeFunction(cx, fun, sourceObject))
    1664           0 :                 return false;
    1665             :         }
    1666             : 
    1667        1408 :         return true;
    1668             :     }
    1669             : 
    1670             :     /* Lazily cloned self-hosted script. */
    1671         556 :     MOZ_ASSERT(fun->isSelfHostedBuiltin());
    1672        1112 :     RootedAtom funAtom(cx, &fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom());
    1673         556 :     if (!funAtom)
    1674           0 :         return false;
    1675        1112 :     Rooted<PropertyName*> funName(cx, funAtom->asPropertyName());
    1676         556 :     return cx->runtime()->cloneSelfHostedFunctionScript(cx, funName, fun);
    1677             : }
    1678             : 
    1679             : void
    1680           0 : JSFunction::maybeRelazify(JSRuntime* rt)
    1681             : {
    1682             :     // Try to relazify functions with a non-lazy script. Note: functions can be
    1683             :     // marked as interpreted despite having no script yet at some points when
    1684             :     // parsing.
    1685           0 :     if (!hasScript() || !u.i.s.script_)
    1686           0 :         return;
    1687             : 
    1688             :     // Don't relazify functions in compartments that are active.
    1689           0 :     JSCompartment* comp = compartment();
    1690           0 :     if (comp->hasBeenEntered() && !rt->allowRelazificationForTesting)
    1691           0 :         return;
    1692             : 
    1693             :     // The caller should have checked we're not in the self-hosting zone (it's
    1694             :     // shared with worker runtimes so relazifying functions in it will race).
    1695           0 :     MOZ_ASSERT(!comp->isSelfHosting);
    1696             : 
    1697             :     // Don't relazify if the compartment is being debugged.
    1698           0 :     if (comp->isDebuggee())
    1699           0 :         return;
    1700             : 
    1701             :     // Don't relazify if the compartment and/or runtime is instrumented to
    1702             :     // collect code coverage for analysis.
    1703           0 :     if (comp->collectCoverageForDebug())
    1704           0 :         return;
    1705             : 
    1706             :     // Don't relazify functions with JIT code.
    1707           0 :     if (!u.i.s.script_->isRelazifiable())
    1708           0 :         return;
    1709             : 
    1710             :     // To delazify self-hosted builtins we need the name of the function
    1711             :     // to clone. This name is stored in the first extended slot. Since
    1712             :     // that slot is sometimes also used for other purposes, make sure it
    1713             :     // contains a string.
    1714           0 :     if (isSelfHostedBuiltin() &&
    1715           0 :         (!isExtended() || !getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).isString()))
    1716             :     {
    1717           0 :         return;
    1718             :     }
    1719             : 
    1720           0 :     JSScript* script = nonLazyScript();
    1721             : 
    1722           0 :     flags_ &= ~INTERPRETED;
    1723           0 :     flags_ |= INTERPRETED_LAZY;
    1724           0 :     LazyScript* lazy = script->maybeLazyScript();
    1725           0 :     u.i.s.lazy_ = lazy;
    1726           0 :     if (lazy) {
    1727           0 :         MOZ_ASSERT(!isSelfHostedBuiltin());
    1728             :     } else {
    1729           0 :         MOZ_ASSERT(isSelfHostedBuiltin());
    1730           0 :         MOZ_ASSERT(isExtended());
    1731           0 :         MOZ_ASSERT(getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->isAtom());
    1732             :     }
    1733             : 
    1734           0 :     comp->scheduleDelazificationForDebugger();
    1735             : }
    1736             : 
    1737             : static bool
    1738           0 : fun_isGenerator(JSContext* cx, unsigned argc, Value* vp)
    1739             : {
    1740           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1741             :     JSFunction* fun;
    1742           0 :     if (!IsFunctionObject(args.thisv(), &fun)) {
    1743           0 :         args.rval().setBoolean(false);
    1744           0 :         return true;
    1745             :     }
    1746             : 
    1747           0 :     args.rval().setBoolean(fun->isStarGenerator() || fun->isLegacyGenerator());
    1748           0 :     return true;
    1749             : }
    1750             : 
    1751             : const JSFunctionSpec js::function_methods[] = {
    1752             : #if JS_HAS_TOSOURCE
    1753             :     JS_FN(js_toSource_str,   fun_toSource,   0,0),
    1754             : #endif
    1755             :     JS_FN(js_toString_str,   fun_toString,   0,0),
    1756             :     JS_FN(js_apply_str,      fun_apply,      2,0),
    1757             :     JS_FN(js_call_str,       fun_call,       1,0),
    1758             :     JS_FN("isGenerator",     fun_isGenerator,0,0),
    1759             :     JS_SELF_HOSTED_FN("bind", "FunctionBind", 2, 0),
    1760             :     JS_SYM_FN(hasInstance, fun_symbolHasInstance, 1, JSPROP_READONLY | JSPROP_PERMANENT),
    1761             :     JS_FS_END
    1762             : };
    1763             : 
    1764             : // ES 2017 draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077 19.2.1.1.1.
    1765             : static bool
    1766           4 : FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generatorKind,
    1767             :                     FunctionAsyncKind asyncKind)
    1768             : {
    1769             :     // Block this call if security callbacks forbid it.
    1770           8 :     Rooted<GlobalObject*> global(cx, &args.callee().global());
    1771           4 :     if (!GlobalObject::isRuntimeCodeGenEnabled(cx, global)) {
    1772           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_FUNCTION);
    1773           0 :         return false;
    1774             :     }
    1775             : 
    1776           4 :     bool isStarGenerator = generatorKind == StarGenerator;
    1777           4 :     bool isAsync = asyncKind == AsyncFunction;
    1778           4 :     MOZ_ASSERT(generatorKind != LegacyGenerator);
    1779             : 
    1780           8 :     RootedScript maybeScript(cx);
    1781             :     const char* filename;
    1782             :     unsigned lineno;
    1783             :     bool mutedErrors;
    1784             :     uint32_t pcOffset;
    1785           8 :     DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
    1786           4 :                                          &mutedErrors);
    1787             : 
    1788           4 :     const char* introductionType = "Function";
    1789           4 :     if (isAsync) {
    1790           0 :         if (isStarGenerator)
    1791           0 :             introductionType = "AsyncGenerator";
    1792             :         else
    1793           0 :             introductionType = "AsyncFunction";
    1794           4 :     } else if (generatorKind != NotGenerator) {
    1795           0 :         introductionType = "GeneratorFunction";
    1796             :     }
    1797             : 
    1798           4 :     const char* introducerFilename = filename;
    1799           4 :     if (maybeScript && maybeScript->scriptSource()->introducerFilename())
    1800           4 :         introducerFilename = maybeScript->scriptSource()->introducerFilename();
    1801             : 
    1802           8 :     CompileOptions options(cx);
    1803           4 :     options.setMutedErrors(mutedErrors)
    1804           4 :            .setFileAndLine(filename, 1)
    1805           8 :            .setNoScriptRval(false)
    1806           8 :            .setIntroductionInfo(introducerFilename, introductionType, lineno, maybeScript, pcOffset);
    1807             : 
    1808           8 :     StringBuffer sb(cx);
    1809             : 
    1810           4 :     if (isAsync) {
    1811           0 :         if (!sb.append("async "))
    1812           0 :             return false;
    1813             :     }
    1814           4 :     if (!sb.append("function"))
    1815           0 :          return false;
    1816           4 :     if (isStarGenerator) {
    1817           0 :         if (!sb.append('*'))
    1818           0 :             return false;
    1819             :     }
    1820             : 
    1821           4 :     if (!sb.append(" anonymous("))
    1822           0 :         return false;
    1823             : 
    1824           4 :     if (args.length() > 1) {
    1825           8 :         RootedString str(cx);
    1826             : 
    1827             :         // Steps 5-6, 9.
    1828           4 :         unsigned n = args.length() - 1;
    1829             : 
    1830          14 :         for (unsigned i = 0; i < n; i++) {
    1831             :             // Steps 9.a-b, 9.d.i-ii.
    1832          10 :             str = ToString<CanGC>(cx, args[i]);
    1833          10 :             if (!str)
    1834           0 :                 return false;
    1835             : 
    1836             :             // Steps 9.b, 9.d.iii.
    1837          10 :             if (!sb.append(str))
    1838           0 :                  return false;
    1839             : 
    1840          10 :             if (i < args.length() - 2) {
    1841             :                 // Step 9.d.iii.
    1842           6 :                 if (!sb.append(","))
    1843           0 :                     return false;
    1844             :             }
    1845             :         }
    1846             :     }
    1847             : 
    1848           4 :     if (!sb.append('\n'))
    1849           0 :         return false;
    1850             : 
    1851             :     // Remember the position of ")".
    1852           8 :     Maybe<uint32_t> parameterListEnd = Some(uint32_t(sb.length()));
    1853           4 :     MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');
    1854             : 
    1855           4 :     if (!sb.append(FunctionConstructorMedialSigils))
    1856           0 :         return false;
    1857             : 
    1858           4 :     if (args.length() > 0) {
    1859             :         // Steps 7-8, 10.
    1860           8 :         RootedString body(cx, ToString<CanGC>(cx, args[args.length() - 1]));
    1861           4 :         if (!body || !sb.append(body))
    1862           0 :              return false;
    1863             :      }
    1864             : 
    1865           4 :     if (!sb.append(FunctionConstructorFinalBrace))
    1866           0 :         return false;
    1867             : 
    1868             :     // The parser only accepts two byte strings.
    1869           4 :     if (!sb.ensureTwoByteChars())
    1870           0 :         return false;
    1871             : 
    1872           8 :     RootedString functionText(cx, sb.finishString());
    1873           4 :     if (!functionText)
    1874           0 :         return false;
    1875             : 
    1876             :     /*
    1877             :      * NB: (new Function) is not lexically closed by its caller, it's just an
    1878             :      * anonymous function in the top-level scope that its constructor inhabits.
    1879             :      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
    1880             :      * and so would a call to f from another top-level's script or function.
    1881             :      */
    1882           8 :     RootedAtom anonymousAtom(cx, cx->names().anonymous);
    1883             : 
    1884             :     // Step 24.
    1885           8 :     RootedObject proto(cx);
    1886           4 :     if (!isAsync) {
    1887           4 :         if (!GetPrototypeFromBuiltinConstructor(cx, args, &proto))
    1888           0 :             return false;
    1889             :     }
    1890             : 
    1891             :     // Step 4.d, use %Generator% as the fallback prototype.
    1892             :     // Also use %Generator% for the unwrapped function of async functions.
    1893           4 :     if (!proto && (isStarGenerator || isAsync)) {
    1894           0 :         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global);
    1895           0 :         if (!proto)
    1896           0 :             return false;
    1897             :     }
    1898             : 
    1899             :     // Step 25-32 (reordered).
    1900           8 :     RootedObject globalLexical(cx, &global->lexicalEnvironment());
    1901           4 :     JSFunction::Flags flags = (isStarGenerator || isAsync)
    1902           4 :                               ? JSFunction::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC
    1903           4 :                               : JSFunction::INTERPRETED_LAMBDA;
    1904           4 :     AllocKind allocKind = isAsync ? AllocKind::FUNCTION_EXTENDED : AllocKind::FUNCTION;
    1905           8 :     RootedFunction fun(cx, NewFunctionWithProto(cx, nullptr, 0,
    1906             :                                                 flags, globalLexical,
    1907             :                                                 anonymousAtom, proto,
    1908           8 :                                                 allocKind, TenuredObject));
    1909           4 :     if (!fun)
    1910           0 :         return false;
    1911             : 
    1912           4 :     if (!JSFunction::setTypeForScriptedFunction(cx, fun))
    1913           0 :         return false;
    1914             : 
    1915             :     // Steps 2.a-b, 3.a-b, 4.a-b, 11-23.
    1916           8 :     AutoStableStringChars stableChars(cx);
    1917           4 :     if (!stableChars.initTwoByte(cx, functionText))
    1918           0 :         return false;
    1919             : 
    1920           4 :     mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
    1921           4 :     SourceBufferHolder::Ownership ownership = stableChars.maybeGiveOwnershipToCaller()
    1922           4 :                                               ? SourceBufferHolder::GiveOwnership
    1923           4 :                                               : SourceBufferHolder::NoOwnership;
    1924             :     bool ok;
    1925           8 :     SourceBufferHolder srcBuf(chars.begin().get(), chars.length(), ownership);
    1926           4 :     if (isAsync) {
    1927           0 :         if (isStarGenerator) {
    1928           0 :             ok = frontend::CompileStandaloneAsyncGenerator(cx, &fun, options, srcBuf,
    1929           0 :                                                            parameterListEnd);
    1930             :         } else {
    1931           0 :             ok = frontend::CompileStandaloneAsyncFunction(cx, &fun, options, srcBuf,
    1932           0 :                                                           parameterListEnd);
    1933             :         }
    1934             :     } else {
    1935           4 :         if (isStarGenerator)
    1936           0 :             ok = frontend::CompileStandaloneGenerator(cx, &fun, options, srcBuf, parameterListEnd);
    1937             :         else
    1938           4 :             ok = frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, parameterListEnd);
    1939             :     }
    1940             : 
    1941             :     // Step 33.
    1942           4 :     args.rval().setObject(*fun);
    1943           4 :     return ok;
    1944             : }
    1945             : 
    1946             : bool
    1947           4 : js::Function(JSContext* cx, unsigned argc, Value* vp)
    1948             : {
    1949           4 :     CallArgs args = CallArgsFromVp(argc, vp);
    1950           4 :     return FunctionConstructor(cx, args, NotGenerator, SyncFunction);
    1951             : }
    1952             : 
    1953             : bool
    1954           0 : js::Generator(JSContext* cx, unsigned argc, Value* vp)
    1955             : {
    1956           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1957           0 :     return FunctionConstructor(cx, args, StarGenerator, SyncFunction);
    1958             : }
    1959             : 
    1960             : bool
    1961           0 : js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp)
    1962             : {
    1963           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1964             : 
    1965             :     // Save the callee before it's reset in FunctionConstructor().
    1966           0 :     RootedObject newTarget(cx);
    1967           0 :     if (args.isConstructing())
    1968           0 :         newTarget = &args.newTarget().toObject();
    1969             :     else
    1970           0 :         newTarget = &args.callee();
    1971             : 
    1972           0 :     if (!FunctionConstructor(cx, args, NotGenerator, AsyncFunction))
    1973           0 :         return false;
    1974             : 
    1975             :     // ES2017, draft rev 0f10dba4ad18de92d47d421f378233a2eae8f077
    1976             :     // 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction, step 24.
    1977           0 :     RootedObject proto(cx);
    1978           0 :     if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
    1979           0 :         return false;
    1980             : 
    1981             :     // 19.2.1.1.1, step 4.d, use %AsyncFunctionPrototype% as the fallback.
    1982           0 :     if (!proto) {
    1983           0 :         proto = GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global());
    1984           0 :         if (!proto)
    1985           0 :             return false;
    1986             :     }
    1987             : 
    1988           0 :     RootedFunction unwrapped(cx, &args.rval().toObject().as<JSFunction>());
    1989           0 :     RootedObject wrapped(cx, WrapAsyncFunctionWithProto(cx, unwrapped, proto));
    1990           0 :     if (!wrapped)
    1991           0 :         return false;
    1992             : 
    1993           0 :     args.rval().setObject(*wrapped);
    1994           0 :     return true;
    1995             : }
    1996             : 
    1997             : bool
    1998           0 : js::AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp)
    1999             : {
    2000           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2001             : 
    2002             :     // Save the callee before its reset in FunctionConstructor().
    2003           0 :     RootedObject newTarget(cx);
    2004           0 :     if (args.isConstructing())
    2005           0 :         newTarget = &args.newTarget().toObject();
    2006             :     else
    2007           0 :         newTarget = &args.callee();
    2008             : 
    2009           0 :     if (!FunctionConstructor(cx, args, StarGenerator, AsyncFunction))
    2010           0 :         return false;
    2011             : 
    2012           0 :     RootedObject proto(cx);
    2013           0 :     if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
    2014           0 :         return false;
    2015             : 
    2016           0 :     if (!proto) {
    2017           0 :         proto = GlobalObject::getOrCreateAsyncGenerator(cx, cx->global());
    2018           0 :         if (!proto)
    2019           0 :             return false;
    2020             :     }
    2021             : 
    2022           0 :     RootedFunction unwrapped(cx, &args.rval().toObject().as<JSFunction>());
    2023           0 :     RootedObject wrapped(cx, WrapAsyncGeneratorWithProto(cx, unwrapped, proto));
    2024           0 :     if (!wrapped)
    2025           0 :         return false;
    2026             : 
    2027           0 :     args.rval().setObject(*wrapped);
    2028           0 :     return true;
    2029             : }
    2030             : 
    2031             : bool
    2032           0 : JSFunction::isBuiltinFunctionConstructor()
    2033             : {
    2034           0 :     return maybeNative() == Function || maybeNative() == Generator;
    2035             : }
    2036             : 
    2037             : bool
    2038        5109 : JSFunction::needsExtraBodyVarEnvironment() const
    2039             : {
    2040        5109 :     MOZ_ASSERT(!isInterpretedLazy());
    2041             : 
    2042        5109 :     if (isNative())
    2043           0 :         return false;
    2044             : 
    2045        5109 :     if (!nonLazyScript()->functionHasExtraBodyVarScope())
    2046        5103 :         return false;
    2047             : 
    2048           6 :     return nonLazyScript()->functionExtraBodyVarScope()->hasEnvironment();
    2049             : }
    2050             : 
    2051             : bool
    2052       21018 : JSFunction::needsNamedLambdaEnvironment() const
    2053             : {
    2054       21018 :     MOZ_ASSERT(!isInterpretedLazy());
    2055             : 
    2056       21018 :     if (!isNamedLambda())
    2057       17732 :         return false;
    2058             : 
    2059        3286 :     LexicalScope* scope = nonLazyScript()->maybeNamedLambdaScope();
    2060        3286 :     if (!scope)
    2061           2 :         return false;
    2062             : 
    2063        3284 :     return scope->hasEnvironment();
    2064             : }
    2065             : 
    2066             : JSFunction*
    2067       44204 : js::NewNativeFunction(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
    2068             :                       gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
    2069             :                       NewObjectKind newKind /* = SingletonObject */)
    2070             : {
    2071       44204 :     MOZ_ASSERT(native);
    2072       88408 :     return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
    2073       88408 :                                 nullptr, atom, nullptr, allocKind, newKind);
    2074             : }
    2075             : 
    2076             : JSFunction*
    2077        1506 : js::NewNativeConstructor(JSContext* cx, Native native, unsigned nargs, HandleAtom atom,
    2078             :                          gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
    2079             :                          NewObjectKind newKind /* = SingletonObject */,
    2080             :                          JSFunction::Flags flags /* = JSFunction::NATIVE_CTOR */)
    2081             : {
    2082        1506 :     MOZ_ASSERT(native);
    2083        1506 :     MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
    2084        3012 :     return NewFunctionWithProto(cx, native, nargs, flags, nullptr, atom,
    2085        3012 :                                 nullptr, allocKind, newKind);
    2086             : }
    2087             : 
    2088             : JSFunction*
    2089       19856 : js::NewScriptedFunction(JSContext* cx, unsigned nargs,
    2090             :                         JSFunction::Flags flags, HandleAtom atom,
    2091             :                         HandleObject proto /* = nullptr */,
    2092             :                         gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
    2093             :                         NewObjectKind newKind /* = GenericObject */,
    2094             :                         HandleObject enclosingEnvArg /* = nullptr */)
    2095             : {
    2096       39712 :     RootedObject enclosingEnv(cx, enclosingEnvArg);
    2097       19856 :     if (!enclosingEnv)
    2098       19845 :         enclosingEnv = &cx->global()->lexicalEnvironment();
    2099       39712 :     return NewFunctionWithProto(cx, nullptr, nargs, flags, enclosingEnv,
    2100       39712 :                                 atom, proto, allocKind, newKind);
    2101             : }
    2102             : 
    2103             : #ifdef DEBUG
    2104             : static bool
    2105      107325 : NewFunctionEnvironmentIsWellFormed(JSContext* cx, HandleObject env)
    2106             : {
    2107             :     // Assert that the terminating environment is null, global, or a debug
    2108             :     // scope proxy. All other cases of polluting global scope behavior are
    2109             :     // handled by EnvironmentObjects (viz. non-syntactic DynamicWithObject and
    2110             :     // NonSyntacticVariablesObject).
    2111      214652 :     RootedObject terminatingEnv(cx, SkipEnvironmentObjects(env));
    2112      251524 :     return !terminatingEnv || terminatingEnv == cx->global() ||
    2113      285110 :            terminatingEnv->is<DebugEnvironmentProxy>();
    2114             : }
    2115             : #endif
    2116             : 
    2117             : JSFunction*
    2118       90626 : js::NewFunctionWithProto(JSContext* cx, Native native,
    2119             :                          unsigned nargs, JSFunction::Flags flags, HandleObject enclosingEnv,
    2120             :                          HandleAtom atom, HandleObject proto,
    2121             :                          gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
    2122             :                          NewObjectKind newKind /* = GenericObject */,
    2123             :                          NewFunctionProtoHandling protoHandling /* = NewFunctionClassProto */)
    2124             : {
    2125       90626 :     MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
    2126       90626 :     MOZ_ASSERT_IF(native, !enclosingEnv);
    2127       90626 :     MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
    2128             : 
    2129      181256 :     RootedObject funobj(cx);
    2130       90627 :     if (protoHandling == NewFunctionClassProto) {
    2131      181255 :         funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
    2132       90629 :                                          newKind);
    2133             :     } else {
    2134           0 :         funobj = NewObjectWithGivenTaggedProto(cx, &JSFunction::class_, AsTaggedProto(proto),
    2135           0 :                                                allocKind, newKind);
    2136             :     }
    2137       90628 :     if (!funobj)
    2138           0 :         return nullptr;
    2139             : 
    2140      181257 :     RootedFunction fun(cx, &funobj->as<JSFunction>());
    2141             : 
    2142       90628 :     if (allocKind == AllocKind::FUNCTION_EXTENDED)
    2143       40105 :         flags = JSFunction::Flags(flags | JSFunction::EXTENDED);
    2144             : 
    2145             :     /* Initialize all function members. */
    2146       90628 :     fun->setArgCount(uint16_t(nargs));
    2147       90628 :     fun->setFlags(flags);
    2148       90625 :     if (fun->isInterpreted()) {
    2149       43736 :         MOZ_ASSERT(!native);
    2150       43736 :         if (fun->isInterpretedLazy())
    2151       19845 :             fun->initLazyScript(nullptr);
    2152             :         else
    2153       23892 :             fun->initScript(nullptr);
    2154       43737 :         fun->initEnvironment(enclosingEnv);
    2155             :     } else {
    2156       46890 :         MOZ_ASSERT(fun->isNative());
    2157       46890 :         MOZ_ASSERT(native);
    2158       46890 :         fun->initNative(native, nullptr);
    2159             :     }
    2160       90627 :     if (allocKind == AllocKind::FUNCTION_EXTENDED)
    2161       40105 :         fun->initializeExtended();
    2162       90627 :     fun->initAtom(atom);
    2163             : 
    2164       90629 :     return fun;
    2165             : }
    2166             : 
    2167             : bool
    2168       30422 : js::CanReuseScriptForClone(JSCompartment* compartment, HandleFunction fun,
    2169             :                            HandleObject newParent)
    2170             : {
    2171       88316 :     if (compartment != fun->compartment() ||
    2172       57894 :         fun->isSingleton() ||
    2173       27472 :         ObjectGroup::useSingletonForClone(fun))
    2174             :     {
    2175        2950 :         return false;
    2176             :     }
    2177             : 
    2178       27472 :     if (newParent->is<GlobalObject>())
    2179           0 :         return true;
    2180             : 
    2181             :     // Don't need to clone the script if newParent is a syntactic scope, since
    2182             :     // in that case we have some actual scope objects on our scope chain and
    2183             :     // whatnot; whoever put them there should be responsible for setting our
    2184             :     // script's flags appropriately.  We hit this case for JSOP_LAMBDA, for
    2185             :     // example.
    2186       27472 :     if (IsSyntacticEnvironment(newParent))
    2187       25462 :         return true;
    2188             : 
    2189             :     // We need to clone the script if we're interpreted and not already marked
    2190             :     // as having a non-syntactic scope. If we're lazy, go ahead and clone the
    2191             :     // script; see the big comment at the end of CopyScriptInternal for the
    2192             :     // explanation of what's going on there.
    2193        6004 :     return !fun->isInterpreted() ||
    2194        6010 :            (fun->hasScript() && fun->nonLazyScript()->hasNonSyntacticScope());
    2195             : }
    2196             : 
    2197             : static inline JSFunction*
    2198       16699 : NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
    2199             :                  gc::AllocKind allocKind, HandleObject proto)
    2200             : {
    2201       33398 :     RootedObject cloneProto(cx, proto);
    2202       16699 :     if (!proto && (fun->isStarGenerator() || fun->isAsync())) {
    2203         297 :         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
    2204         297 :         if (!cloneProto)
    2205           0 :             return nullptr;
    2206             :     }
    2207             : 
    2208       33398 :     JSObject* cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
    2209       16699 :                                                  allocKind, newKind);
    2210       16699 :     if (!cloneobj)
    2211           0 :         return nullptr;
    2212       33398 :     RootedFunction clone(cx, &cloneobj->as<JSFunction>());
    2213             : 
    2214       16699 :     uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
    2215       16699 :     if (allocKind == AllocKind::FUNCTION_EXTENDED)
    2216        9602 :         flags |= JSFunction::EXTENDED;
    2217             : 
    2218       16699 :     clone->setArgCount(fun->nargs());
    2219       16699 :     clone->setFlags(flags);
    2220             : 
    2221       16699 :     JSAtom* atom = fun->displayAtom();
    2222       16699 :     if (atom)
    2223       16298 :         cx->markAtom(atom);
    2224       16699 :     clone->initAtom(atom);
    2225             : 
    2226       16699 :     if (allocKind == AllocKind::FUNCTION_EXTENDED) {
    2227        9602 :         if (fun->isExtended() && fun->compartment() == cx->compartment()) {
    2228       22716 :             for (unsigned i = 0; i < FunctionExtended::NUM_EXTENDED_SLOTS; i++)
    2229       15144 :                 clone->initExtendedSlot(i, fun->getExtendedSlot(i));
    2230             :         } else {
    2231        2030 :             clone->initializeExtended();
    2232             :         }
    2233             :     }
    2234             : 
    2235       16699 :     return clone;
    2236             : }
    2237             : 
    2238             : JSFunction*
    2239       13723 : js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject enclosingEnv,
    2240             :                              gc::AllocKind allocKind /* = FUNCTION */ ,
    2241             :                              NewObjectKind newKind /* = GenericObject */,
    2242             :                              HandleObject proto /* = nullptr */)
    2243             : {
    2244       13723 :     MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
    2245       13723 :     MOZ_ASSERT(!fun->isBoundFunction());
    2246       13723 :     MOZ_ASSERT(CanReuseScriptForClone(cx->compartment(), fun, enclosingEnv));
    2247             : 
    2248       27446 :     RootedFunction clone(cx, NewFunctionClone(cx, fun, newKind, allocKind, proto));
    2249       13723 :     if (!clone)
    2250           0 :         return nullptr;
    2251             : 
    2252       13723 :     if (fun->hasScript()) {
    2253       12340 :         clone->initScript(fun->nonLazyScript());
    2254       12340 :         clone->initEnvironment(enclosingEnv);
    2255        1383 :     } else if (fun->isInterpretedLazy()) {
    2256        1383 :         MOZ_ASSERT(fun->compartment() == clone->compartment());
    2257        1383 :         LazyScript* lazy = fun->lazyScriptOrNull();
    2258        1383 :         clone->initLazyScript(lazy);
    2259        1383 :         clone->initEnvironment(enclosingEnv);
    2260             :     } else {
    2261           0 :         clone->initNative(fun->native(), fun->jitInfo());
    2262             :     }
    2263             : 
    2264             :     /*
    2265             :      * Clone the function, reusing its script. We can use the same group as
    2266             :      * the original function provided that its prototype is correct.
    2267             :      */
    2268       13723 :     if (fun->staticPrototype() == clone->staticPrototype())
    2269       13697 :         clone->setGroup(fun->group());
    2270       13723 :     return clone;
    2271             : }
    2272             : 
    2273             : JSFunction*
    2274        2976 : js::CloneFunctionAndScript(JSContext* cx, HandleFunction fun, HandleObject enclosingEnv,
    2275             :                            HandleScope newScope, gc::AllocKind allocKind /* = FUNCTION */,
    2276             :                            HandleObject proto /* = nullptr */)
    2277             : {
    2278        2976 :     MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
    2279        2976 :     MOZ_ASSERT(!fun->isBoundFunction());
    2280             : 
    2281        5952 :     JSScript::AutoDelazify funScript(cx);
    2282        2976 :     if (fun->isInterpreted()) {
    2283        1463 :         funScript = fun;
    2284        1463 :         if (!funScript)
    2285           0 :             return nullptr;
    2286             :     }
    2287             : 
    2288        5952 :     RootedFunction clone(cx, NewFunctionClone(cx, fun, SingletonObject, allocKind, proto));
    2289        2976 :     if (!clone)
    2290           0 :         return nullptr;
    2291             : 
    2292        2976 :     if (fun->hasScript()) {
    2293        1463 :         clone->initScript(nullptr);
    2294        1463 :         clone->initEnvironment(enclosingEnv);
    2295             :     } else {
    2296        1513 :         clone->initNative(fun->native(), fun->jitInfo());
    2297             :     }
    2298             : 
    2299             :     /*
    2300             :      * Across compartments or if we have to introduce a non-syntactic scope we
    2301             :      * have to clone the script for interpreted functions. Cross-compartment
    2302             :      * cloning only happens via JSAPI (JS::CloneFunctionObject) which
    2303             :      * dynamically ensures that 'script' has no enclosing lexical scope (only
    2304             :      * the global scope or other non-lexical scope).
    2305             :      */
    2306             : #ifdef DEBUG
    2307        5952 :     RootedObject terminatingEnv(cx, enclosingEnv);
    2308        8780 :     while (IsSyntacticEnvironment(terminatingEnv))
    2309        2902 :         terminatingEnv = terminatingEnv->enclosingEnvironment();
    2310        2976 :     MOZ_ASSERT_IF(!terminatingEnv->is<GlobalObject>(),
    2311             :                   newScope->hasOnChain(ScopeKind::NonSyntactic));
    2312             : #endif
    2313             : 
    2314        2976 :     if (clone->isInterpreted()) {
    2315        2926 :         RootedScript script(cx, fun->nonLazyScript());
    2316        1463 :         MOZ_ASSERT(script->compartment() == fun->compartment());
    2317        1463 :         MOZ_ASSERT(cx->compartment() == clone->compartment(),
    2318             :                    "Otherwise we could relazify clone below!");
    2319             : 
    2320        2926 :         RootedScript clonedScript(cx, CloneScriptIntoFunction(cx, newScope, clone, script));
    2321        1463 :         if (!clonedScript)
    2322           0 :             return nullptr;
    2323        1463 :         Debugger::onNewScript(cx, clonedScript);
    2324             :     }
    2325             : 
    2326        2976 :     return clone;
    2327             : }
    2328             : 
    2329             : /*
    2330             :  * Return an atom for use as the name of a builtin method with the given
    2331             :  * property id.
    2332             :  *
    2333             :  * Function names are always strings. If id is the well-known @@iterator
    2334             :  * symbol, this returns "[Symbol.iterator]".  If a prefix is supplied the final
    2335             :  * name is |prefix + " " + name|. A prefix cannot be supplied if id is a
    2336             :  * symbol value.
    2337             :  *
    2338             :  * Implements steps 3-5 of 9.2.11 SetFunctionName in ES2016.
    2339             :  */
    2340             : JSAtom*
    2341       61043 : js::IdToFunctionName(JSContext* cx, HandleId id,
    2342             :                      FunctionPrefixKind prefixKind /* = FunctionPrefixKind::None */)
    2343             : {
    2344             :     // No prefix fastpath.
    2345       61043 :     if (JSID_IS_ATOM(id) && prefixKind == FunctionPrefixKind::None)
    2346       44396 :         return JSID_TO_ATOM(id);
    2347             : 
    2348             :     // Step 3 (implicit).
    2349             : 
    2350             :     // Step 4.
    2351       16647 :     if (JSID_IS_SYMBOL(id)) {
    2352             :         // Step 4.a.
    2353        4630 :         RootedAtom desc(cx, JSID_TO_SYMBOL(id)->description());
    2354             : 
    2355             :         // Step 4.b, no prefix fastpath.
    2356        2315 :         if (!desc && prefixKind == FunctionPrefixKind::None)
    2357           0 :             return cx->names().empty;
    2358             : 
    2359             :         // Step 5 (reordered).
    2360        4630 :         StringBuffer sb(cx);
    2361        2315 :         if (prefixKind == FunctionPrefixKind::Get) {
    2362           0 :             if (!sb.append("get "))
    2363           0 :                 return nullptr;
    2364        2315 :         } else if (prefixKind == FunctionPrefixKind::Set) {
    2365           0 :             if (!sb.append("set "))
    2366           0 :                 return nullptr;
    2367             :         }
    2368             : 
    2369             :         // Step 4.b.
    2370        2315 :         if (desc) {
    2371             :             // Step 4.c.
    2372        2315 :             if (!sb.append('[') || !sb.append(desc) || !sb.append(']'))
    2373           0 :                 return nullptr;
    2374             :         }
    2375        2315 :         return sb.finishAtom();
    2376             :     }
    2377             : 
    2378       28664 :     RootedValue idv(cx, IdToValue(id));
    2379       28664 :     RootedAtom name(cx, ToAtom<CanGC>(cx, idv));
    2380       14332 :     if (!name)
    2381           0 :         return nullptr;
    2382             : 
    2383             :     // Step 5.
    2384       14332 :     return NameToFunctionName(cx, name, prefixKind);
    2385             : }
    2386             : 
    2387             : JSAtom*
    2388       14332 : js::NameToFunctionName(JSContext* cx, HandleAtom name,
    2389             :                        FunctionPrefixKind prefixKind /* = FunctionPrefixKind::None */)
    2390             : {
    2391       14332 :     if (prefixKind == FunctionPrefixKind::None)
    2392           0 :         return name;
    2393             : 
    2394       28664 :     StringBuffer sb(cx);
    2395       14332 :     if (prefixKind == FunctionPrefixKind::Get) {
    2396        9535 :         if (!sb.append("get "))
    2397           0 :             return nullptr;
    2398             :     } else {
    2399        4797 :         if (!sb.append("set "))
    2400           0 :             return nullptr;
    2401             :     }
    2402       14332 :     if (!sb.append(name))
    2403           0 :         return nullptr;
    2404       14332 :     return sb.finishAtom();
    2405             : }
    2406             : 
    2407             : bool
    2408          10 : js::SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue name,
    2409             :                                FunctionPrefixKind prefixKind)
    2410             : {
    2411          10 :     MOZ_ASSERT(name.isString() || name.isSymbol() || name.isNumber());
    2412             : 
    2413          10 :     if (fun->isClassConstructor()) {
    2414             :         // A class may have static 'name' method or accessor.
    2415          14 :         RootedId nameId(cx, NameToId(cx->names().name));
    2416             :         bool result;
    2417           7 :         if (!HasOwnProperty(cx, fun, nameId, &result))
    2418           0 :             return false;
    2419             : 
    2420           7 :         if (result)
    2421           0 :             return true;
    2422             :     } else {
    2423             :         // Anonymous function shouldn't have own 'name' property at this point.
    2424           3 :         MOZ_ASSERT(!fun->containsPure(cx->names().name));
    2425             :     }
    2426             : 
    2427          20 :     RootedId id(cx);
    2428          10 :     if (!ValueToId<CanGC>(cx, name, &id))
    2429           0 :         return false;
    2430             : 
    2431          20 :     RootedAtom funNameAtom(cx, IdToFunctionName(cx, id, prefixKind));
    2432          10 :     if (!funNameAtom)
    2433           0 :         return false;
    2434             : 
    2435          20 :     RootedValue funNameVal(cx, StringValue(funNameAtom));
    2436          10 :     if (!NativeDefineProperty(cx, fun, cx->names().name, funNameVal, nullptr, nullptr,
    2437             :                               JSPROP_READONLY))
    2438             :     {
    2439           0 :         return false;
    2440             :     }
    2441          10 :     return true;
    2442             : }
    2443             : 
    2444             : JSFunction*
    2445        1412 : js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
    2446             :                    unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */)
    2447             : {
    2448             :     GetterOp gop;
    2449             :     SetterOp sop;
    2450        1412 :     if (flags & JSFUN_STUB_GSOPS) {
    2451             :         /*
    2452             :          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
    2453             :          * the defined property's attributes. This allows us to encode another,
    2454             :          * internal flag using the same bit, JSFUN_EXPR_CLOSURE -- see jsfun.h
    2455             :          * for more on this.
    2456             :          */
    2457         605 :         flags &= ~JSFUN_STUB_GSOPS;
    2458         605 :         gop = nullptr;
    2459         605 :         sop = nullptr;
    2460             :     } else {
    2461         807 :         gop = obj->getClass()->getGetProperty();
    2462         807 :         sop = obj->getClass()->getSetProperty();
    2463         807 :         MOZ_ASSERT(gop != JS_PropertyStub);
    2464         807 :         MOZ_ASSERT(sop != JS_StrictPropertyStub);
    2465             :     }
    2466             : 
    2467        2824 :     RootedAtom atom(cx, IdToFunctionName(cx, id));
    2468        1412 :     if (!atom)
    2469           0 :         return nullptr;
    2470             : 
    2471        2824 :     RootedFunction fun(cx);
    2472        1412 :     if (!native)
    2473           0 :         fun = NewScriptedFunction(cx, nargs,
    2474             :                                   JSFunction::INTERPRETED_LAZY, atom,
    2475             :                                   /* proto = */ nullptr,
    2476           0 :                                   allocKind, GenericObject, obj);
    2477        1412 :     else if (flags & JSFUN_CONSTRUCTOR)
    2478         298 :         fun = NewNativeConstructor(cx, native, nargs, atom, allocKind);
    2479             :     else
    2480        1114 :         fun = NewNativeFunction(cx, native, nargs, atom, allocKind);
    2481             : 
    2482        1412 :     if (!fun)
    2483           0 :         return nullptr;
    2484             : 
    2485        2824 :     RootedValue funVal(cx, ObjectValue(*fun));
    2486        1412 :     if (!DefineProperty(cx, obj, id, funVal, gop, sop, flags & ~JSFUN_FLAGS_MASK))
    2487           0 :         return nullptr;
    2488             : 
    2489        1412 :     return fun;
    2490             : }
    2491             : 
    2492             : void
    2493           0 : js::ReportIncompatibleMethod(JSContext* cx, const CallArgs& args, const Class* clasp)
    2494             : {
    2495           0 :     RootedValue thisv(cx, args.thisv());
    2496             : 
    2497             : #ifdef DEBUG
    2498           0 :     if (thisv.isObject()) {
    2499           0 :         MOZ_ASSERT(thisv.toObject().getClass() != clasp ||
    2500             :                    !thisv.toObject().isNative() ||
    2501             :                    !thisv.toObject().staticPrototype() ||
    2502             :                    thisv.toObject().staticPrototype()->getClass() != clasp);
    2503           0 :     } else if (thisv.isString()) {
    2504           0 :         MOZ_ASSERT(clasp != &StringObject::class_);
    2505           0 :     } else if (thisv.isNumber()) {
    2506           0 :         MOZ_ASSERT(clasp != &NumberObject::class_);
    2507           0 :     } else if (thisv.isBoolean()) {
    2508           0 :         MOZ_ASSERT(clasp != &BooleanObject::class_);
    2509           0 :     } else if (thisv.isSymbol()) {
    2510           0 :         MOZ_ASSERT(clasp != &SymbolObject::class_);
    2511             :     } else {
    2512           0 :         MOZ_ASSERT(thisv.isUndefined() || thisv.isNull());
    2513             :     }
    2514             : #endif
    2515             : 
    2516           0 :     if (JSFunction* fun = ReportIfNotFunction(cx, args.calleev())) {
    2517           0 :         JSAutoByteString funNameBytes;
    2518           0 :         if (const char* funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
    2519           0 :             JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
    2520           0 :                                        clasp->name, funName, InformalValueTypeName(thisv));
    2521             :         }
    2522             :     }
    2523           0 : }
    2524             : 
    2525             : void
    2526           0 : js::ReportIncompatible(JSContext* cx, const CallArgs& args)
    2527             : {
    2528           0 :     if (JSFunction* fun = ReportIfNotFunction(cx, args.calleev())) {
    2529           0 :         JSAutoByteString funNameBytes;
    2530           0 :         if (const char* funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
    2531           0 :             JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_METHOD,
    2532           0 :                                        funName, "method", InformalValueTypeName(args.thisv()));
    2533             :         }
    2534             :     }
    2535           0 : }
    2536             : 
    2537             : namespace JS {
    2538             : namespace detail {
    2539             : 
    2540             : JS_PUBLIC_API(void)
    2541        1360 : CheckIsValidConstructible(const Value& calleev)
    2542             : {
    2543        1360 :     JSObject* callee = &calleev.toObject();
    2544        1360 :     if (callee->is<JSFunction>())
    2545        1326 :         MOZ_ASSERT(callee->as<JSFunction>().isConstructor());
    2546             :     else
    2547          34 :         MOZ_ASSERT(callee->constructHook() != nullptr);
    2548        1360 : }
    2549             : 
    2550             : } // namespace detail
    2551             : } // namespace JS

Generated by: LCOV version 1.13