tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

JSFunction.cpp (65542B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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 "vm/JSFunction-inl.h"
     12 
     13 #include "mozilla/Maybe.h"
     14 
     15 #include <string.h>
     16 
     17 #include "jsapi.h"
     18 #include "jstypes.h"
     19 
     20 #include "builtin/Array.h"
     21 #include "builtin/BigInt.h"
     22 #include "builtin/Object.h"
     23 #include "builtin/Symbol.h"
     24 #include "frontend/BytecodeCompiler.h"  // frontend::{CompileStandaloneFunction, CompileStandaloneGenerator, CompileStandaloneAsyncFunction, CompileStandaloneAsyncGenerator, DelazifyCanonicalScriptedFunction}
     25 #include "frontend/FrontendContext.h"  // AutoReportFrontendContext, ManualReportFrontendContext
     26 #include "frontend/Stencil.h"  // js::DumpFunctionFlagsItems
     27 #include "jit/InlinableNatives.h"
     28 #include "jit/Ion.h"
     29 #include "js/CallNonGenericMethod.h"
     30 #include "js/CompilationAndEvaluation.h"
     31 #include "js/CompileOptions.h"
     32 #include "js/friend/ErrorMessages.h"  // js::GetErrorMessage, JSMSG_*
     33 #include "js/friend/StackLimits.h"    // js::AutoCheckRecursionLimit
     34 #include "js/Printer.h"               // js::GenericPrinter
     35 #include "js/PropertySpec.h"
     36 #include "js/SourceText.h"
     37 #include "js/StableStringChars.h"
     38 #include "js/Wrapper.h"
     39 #include "util/DifferentialTesting.h"
     40 #include "util/StringBuilder.h"
     41 #include "util/Text.h"
     42 #include "vm/BooleanObject.h"
     43 #include "vm/BoundFunctionObject.h"
     44 #include "vm/Compartment.h"
     45 #include "vm/FunctionFlags.h"          // js::FunctionFlags
     46 #include "vm/GeneratorAndAsyncKind.h"  // js::GeneratorKind, js::FunctionAsyncKind
     47 #include "vm/GlobalObject.h"
     48 #include "vm/Interpreter.h"
     49 #include "vm/JSAtomUtils.h"  // ToAtom
     50 #include "vm/JSContext.h"
     51 #include "vm/JSObject.h"
     52 #include "vm/JSONPrinter.h"  // js::JSONPrinter
     53 #include "vm/JSScript.h"
     54 #include "vm/NumberObject.h"
     55 #include "vm/PlainObject.h"  // js::PlainObject
     56 #include "vm/SelfHosting.h"
     57 #include "vm/Shape.h"
     58 #include "vm/StringObject.h"
     59 #include "wasm/AsmJS.h"
     60 #include "wasm/WasmCode.h"
     61 #include "wasm/WasmInstance.h"
     62 #include "vm/Interpreter-inl.h"
     63 #include "vm/JSScript-inl.h"
     64 
     65 using namespace js;
     66 
     67 using mozilla::Maybe;
     68 using mozilla::Some;
     69 
     70 using JS::AutoStableStringChars;
     71 using JS::CompileOptions;
     72 using JS::SourceText;
     73 
     74 static bool fun_enumerate(JSContext* cx, HandleObject obj) {
     75  MOZ_ASSERT(obj->is<JSFunction>());
     76 
     77  RootedId id(cx);
     78  bool found;
     79 
     80  if (obj->as<JSFunction>().needsPrototypeProperty()) {
     81    id = NameToId(cx->names().prototype);
     82    if (!HasOwnProperty(cx, obj, id, &found)) {
     83      return false;
     84    }
     85  }
     86 
     87  if (!obj->as<JSFunction>().hasResolvedLength()) {
     88    id = NameToId(cx->names().length);
     89    if (!HasOwnProperty(cx, obj, id, &found)) {
     90      return false;
     91    }
     92  }
     93 
     94  if (!obj->as<JSFunction>().hasResolvedName()) {
     95    id = NameToId(cx->names().name);
     96    if (!HasOwnProperty(cx, obj, id, &found)) {
     97      return false;
     98    }
     99  }
    100 
    101  return true;
    102 }
    103 
    104 static bool IsFunction(HandleValue v) {
    105  return v.isObject() && v.toObject().is<JSFunction>();
    106 }
    107 
    108 static bool AdvanceToActiveCallLinear(JSContext* cx,
    109                                      NonBuiltinScriptFrameIter& iter,
    110                                      HandleFunction fun) {
    111  MOZ_ASSERT(!fun->isBuiltin());
    112 
    113  for (; !iter.done(); ++iter) {
    114    if (!iter.isFunctionFrame()) {
    115      continue;
    116    }
    117    if (iter.matchCallee(cx, fun)) {
    118      return true;
    119    }
    120  }
    121  return false;
    122 }
    123 
    124 void js::ThrowTypeErrorBehavior(JSContext* cx) {
    125  JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    126                            JSMSG_THROW_TYPE_ERROR);
    127 }
    128 
    129 static bool IsSloppyNormalFunction(JSFunction* fun) {
    130  // FunctionDeclaration or FunctionExpression in sloppy mode.
    131  if (fun->kind() == FunctionFlags::NormalFunction) {
    132    if (fun->isBuiltin()) {
    133      return false;
    134    }
    135 
    136    if (fun->isGenerator() || fun->isAsync()) {
    137      return false;
    138    }
    139 
    140    MOZ_ASSERT(fun->isInterpreted());
    141    return !fun->strict();
    142  }
    143 
    144  // Or asm.js function in sloppy mode.
    145  if (fun->kind() == FunctionFlags::AsmJS) {
    146    return !IsAsmJSStrictModeModuleOrFunction(fun);
    147  }
    148 
    149  return false;
    150 }
    151 
    152 // Beware: this function can be invoked on *any* function! That includes
    153 // natives, strict mode functions, bound functions, arrow functions,
    154 // self-hosted functions and constructors, asm.js functions, functions with
    155 // destructuring arguments and/or a rest argument, and probably a few more I
    156 // forgot. Turn back and save yourself while you still can. It's too late for
    157 // me.
    158 static bool ArgumentsRestrictions(JSContext* cx, HandleFunction fun) {
    159  // Throw unless the function is a sloppy, normal function.
    160  // TODO (bug 1057208): ensure semantics are correct for all possible
    161  // pairings of callee/caller.
    162  if (!IsSloppyNormalFunction(fun)) {
    163    ThrowTypeErrorBehavior(cx);
    164    return false;
    165  }
    166 
    167  return true;
    168 }
    169 
    170 static bool ArgumentsGetterImpl(JSContext* cx, const CallArgs& args) {
    171  MOZ_ASSERT(IsFunction(args.thisv()));
    172 
    173  RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
    174  if (!ArgumentsRestrictions(cx, fun)) {
    175    return false;
    176  }
    177 
    178  // Function.arguments isn't standard (not even Annex B), so it isn't
    179  // worth the effort to guarantee that we can always recover it from
    180  // an Ion frame. Always return null for differential fuzzing.
    181  if (js::SupportDifferentialTesting()) {
    182    args.rval().setNull();
    183    return true;
    184  }
    185 
    186  // Return null if this function wasn't found on the stack.
    187  NonBuiltinScriptFrameIter iter(cx);
    188  if (!AdvanceToActiveCallLinear(cx, iter, fun)) {
    189    args.rval().setNull();
    190    return true;
    191  }
    192 
    193  Rooted<ArgumentsObject*> argsobj(cx,
    194                                   ArgumentsObject::createUnexpected(cx, iter));
    195  if (!argsobj) {
    196    return false;
    197  }
    198 
    199 #ifndef JS_CODEGEN_NONE
    200  // Disabling compiling of this script in IonMonkey.  IonMonkey doesn't
    201  // guarantee |f.arguments| can be fully recovered, so we try to mitigate
    202  // observing this behavior by detecting its use early.
    203  JSScript* script = iter.script();
    204  jit::ForbidCompilation(cx, script);
    205 #endif
    206 
    207  args.rval().setObject(*argsobj);
    208  return true;
    209 }
    210 
    211 static bool ArgumentsGetter(JSContext* cx, unsigned argc, Value* vp) {
    212  CallArgs args = CallArgsFromVp(argc, vp);
    213  return CallNonGenericMethod<IsFunction, ArgumentsGetterImpl>(cx, args);
    214 }
    215 
    216 static bool ArgumentsSetterImpl(JSContext* cx, const CallArgs& args) {
    217  MOZ_ASSERT(IsFunction(args.thisv()));
    218 
    219  RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
    220  if (!ArgumentsRestrictions(cx, fun)) {
    221    return false;
    222  }
    223 
    224  // If the function passes the gauntlet, return |undefined|.
    225  args.rval().setUndefined();
    226  return true;
    227 }
    228 
    229 static bool ArgumentsSetter(JSContext* cx, unsigned argc, Value* vp) {
    230  CallArgs args = CallArgsFromVp(argc, vp);
    231  return CallNonGenericMethod<IsFunction, ArgumentsSetterImpl>(cx, args);
    232 }
    233 
    234 // Beware: this function can be invoked on *any* function! That includes
    235 // natives, strict mode functions, bound functions, arrow functions,
    236 // self-hosted functions and constructors, asm.js functions, functions with
    237 // destructuring arguments and/or a rest argument, and probably a few more I
    238 // forgot. Turn back and save yourself while you still can. It's too late for
    239 // me.
    240 static bool CallerRestrictions(JSContext* cx, HandleFunction fun) {
    241  // Throw unless the function is a sloppy, normal function.
    242  // TODO (bug 1057208): ensure semantics are correct for all possible
    243  // pairings of callee/caller.
    244  if (!IsSloppyNormalFunction(fun)) {
    245    ThrowTypeErrorBehavior(cx);
    246    return false;
    247  }
    248 
    249  return true;
    250 }
    251 
    252 static bool CallerGetterImpl(JSContext* cx, const CallArgs& args) {
    253  MOZ_ASSERT(IsFunction(args.thisv()));
    254 
    255  // Beware!  This function can be invoked on *any* function!  It can't
    256  // assume it'll never be invoked on natives, strict mode functions, bound
    257  // functions, or anything else that ordinarily has immutable .caller
    258  // defined with [[ThrowTypeError]].
    259  RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
    260  if (!CallerRestrictions(cx, fun)) {
    261    return false;
    262  }
    263 
    264  // Also return null if this function wasn't found on the stack.
    265  NonBuiltinScriptFrameIter iter(cx);
    266  if (!AdvanceToActiveCallLinear(cx, iter, fun)) {
    267    args.rval().setNull();
    268    return true;
    269  }
    270 
    271  ++iter;
    272  while (!iter.done() && iter.isEvalFrame()) {
    273    ++iter;
    274  }
    275 
    276  if (iter.done() || !iter.isFunctionFrame()) {
    277    args.rval().setNull();
    278    return true;
    279  }
    280 
    281  RootedObject caller(cx, iter.callee(cx));
    282  if (!cx->compartment()->wrap(cx, &caller)) {
    283    return false;
    284  }
    285 
    286  // Censor the caller if we don't have full access to it.  If we do, but the
    287  // caller is a function with strict mode code, throw a TypeError per ES5.
    288  // If we pass these checks, we can return the computed caller.
    289  {
    290    JSObject* callerObj = CheckedUnwrapStatic(caller);
    291    if (!callerObj) {
    292      args.rval().setNull();
    293      return true;
    294    }
    295 
    296    if (JS_IsDeadWrapper(callerObj)) {
    297      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    298                                JSMSG_DEAD_OBJECT);
    299      return false;
    300    }
    301 
    302    JSFunction* callerFun = &callerObj->as<JSFunction>();
    303    MOZ_ASSERT(!callerFun->isBuiltin(),
    304               "non-builtin iterator returned a builtin?");
    305 
    306    if (callerFun->strict() || callerFun->isAsync() ||
    307        callerFun->isGenerator()) {
    308      args.rval().setNull();
    309      return true;
    310    }
    311  }
    312 
    313  args.rval().setObject(*caller);
    314  return true;
    315 }
    316 
    317 static bool CallerGetter(JSContext* cx, unsigned argc, Value* vp) {
    318  CallArgs args = CallArgsFromVp(argc, vp);
    319  return CallNonGenericMethod<IsFunction, CallerGetterImpl>(cx, args);
    320 }
    321 
    322 static bool CallerSetterImpl(JSContext* cx, const CallArgs& args) {
    323  MOZ_ASSERT(IsFunction(args.thisv()));
    324 
    325  // We just have to return |undefined|, but first we call CallerGetterImpl
    326  // because we need the same strict-mode and security checks.
    327 
    328  if (!CallerGetterImpl(cx, args)) {
    329    return false;
    330  }
    331 
    332  args.rval().setUndefined();
    333  return true;
    334 }
    335 
    336 static bool CallerSetter(JSContext* cx, unsigned argc, Value* vp) {
    337  CallArgs args = CallArgsFromVp(argc, vp);
    338  return CallNonGenericMethod<IsFunction, CallerSetterImpl>(cx, args);
    339 }
    340 
    341 static const JSPropertySpec function_properties[] = {
    342    JS_PSGS("arguments", ArgumentsGetter, ArgumentsSetter, 0),
    343    JS_PSGS("caller", CallerGetter, CallerSetter, 0),
    344    JS_PS_END,
    345 };
    346 
    347 static bool ResolveInterpretedFunctionPrototype(JSContext* cx,
    348                                                HandleFunction fun,
    349                                                HandleId id) {
    350  MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
    351  MOZ_ASSERT(id == NameToId(cx->names().prototype));
    352 
    353  // Assert that fun is not a compiler-created function object, which
    354  // must never leak to script or embedding code and then be mutated.
    355  // Also assert that fun is not bound, per the ES5 15.3.4.5 ref above.
    356  MOZ_ASSERT(!IsInternalFunctionObject(*fun));
    357 
    358  // Make the prototype object an instance of Object with the same parent as
    359  // the function object itself, unless the function is an ES6 generator.  In
    360  // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
    361  // the GeneratorObjectPrototype singleton.
    362  bool isGenerator = fun->isGenerator();
    363  Rooted<GlobalObject*> global(cx, &fun->global());
    364  RootedObject objProto(cx);
    365  if (isGenerator && fun->isAsync()) {
    366    objProto = GlobalObject::getOrCreateAsyncGeneratorPrototype(cx, global);
    367  } else if (isGenerator) {
    368    objProto = GlobalObject::getOrCreateGeneratorObjectPrototype(cx, global);
    369  } else {
    370    objProto = &global->getObjectPrototype();
    371  }
    372  if (!objProto) {
    373    return false;
    374  }
    375 
    376  Rooted<PlainObject*> proto(
    377      cx, NewPlainObjectWithProto(cx, objProto, TenuredObject));
    378  if (!proto) {
    379    return false;
    380  }
    381 
    382  // Per ES5 13.2 the prototype's .constructor property is configurable,
    383  // non-enumerable, and writable.  However, per the 15 July 2013 ES6 draft,
    384  // section 15.19.3, the .prototype of a generator function does not link
    385  // back with a .constructor.
    386  if (!isGenerator) {
    387    RootedValue objVal(cx, ObjectValue(*fun));
    388    if (!DefineDataProperty(cx, proto, cx->names().constructor, objVal, 0)) {
    389      return false;
    390    }
    391  }
    392 
    393  // Per ES5 15.3.5.2 a user-defined function's .prototype property is
    394  // initially non-configurable, non-enumerable, and writable.
    395  RootedValue protoVal(cx, ObjectValue(*proto));
    396  return DefineDataProperty(cx, fun, id, protoVal,
    397                            JSPROP_PERMANENT | JSPROP_RESOLVING);
    398 }
    399 
    400 bool JSFunction::needsPrototypeProperty() {
    401  /*
    402   * Built-in functions do not have a .prototype property per ECMA-262,
    403   * or (Object.prototype, Function.prototype, etc.) have that property
    404   * created eagerly.
    405   *
    406   * ES6 9.2.8 MakeConstructor defines the .prototype property on constructors.
    407   * Generators are not constructors, but they have a .prototype property
    408   * anyway, according to errata to ES6. See bug 1191486.
    409   *
    410   * Thus all of the following don't get a .prototype property:
    411   * - Methods (that are not class-constructors or generators)
    412   * - Arrow functions
    413   * - Function.prototype
    414   * - Async functions
    415   */
    416  return !isBuiltin() && (isConstructor() || isGenerator());
    417 }
    418 
    419 bool JSFunction::hasNonConfigurablePrototypeDataProperty() {
    420  if (!isBuiltin()) {
    421    return needsPrototypeProperty();
    422  }
    423 
    424  if (isSelfHostedBuiltin()) {
    425    // Self-hosted constructors have a non-configurable .prototype data
    426    // property.
    427    if (!isConstructor()) {
    428      return false;
    429    }
    430 #ifdef DEBUG
    431    PropertyName* prototypeName =
    432        runtimeFromMainThread()->commonNames->prototype;
    433    Maybe<PropertyInfo> prop = lookupPure(prototypeName);
    434    MOZ_ASSERT(prop.isSome());
    435    MOZ_ASSERT(prop->isDataProperty());
    436    MOZ_ASSERT(!prop->configurable());
    437 #endif
    438    return true;
    439  }
    440 
    441  if (!isConstructor()) {
    442    // We probably don't have a .prototype property. Avoid the lookup below.
    443    return false;
    444  }
    445 
    446  PropertyName* prototypeName = runtimeFromMainThread()->commonNames->prototype;
    447  Maybe<PropertyInfo> prop = lookupPure(prototypeName);
    448  return prop.isSome() && prop->isDataProperty() && !prop->configurable();
    449 }
    450 
    451 uint32_t JSFunction::wasmFuncIndex() const {
    452  MOZ_ASSERT(isWasm() || isAsmJSNative());
    453  if (!isNativeWithJitEntry()) {
    454    uintptr_t tagged = uintptr_t(nativeJitInfoOrInterpretedScript());
    455    MOZ_ASSERT(tagged & 1);
    456    return tagged >> 1;
    457  }
    458  return wasmInstance().code().funcIndexFromJitEntry(wasmJitEntry());
    459 }
    460 
    461 void JSFunction::initWasm(uint32_t funcIndex, wasm::Instance* instance,
    462                          const wasm::SuperTypeVector* superTypeVector,
    463                          void* uncheckedCallEntry) {
    464  MOZ_ASSERT(isWasm() || isAsmJSNative());
    465  MOZ_ASSERT(!isWasmWithJitEntry());
    466  MOZ_ASSERT(!nativeJitInfoOrInterpretedScript());
    467 
    468  // Set the func index, see comment on the field for why we set the low bit.
    469  uintptr_t tagged = (uintptr_t(funcIndex) << 1) | 1;
    470  setNativeJitInfoOrInterpretedScript(reinterpret_cast<void*>(tagged));
    471  // Set the instance
    472  setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT,
    473                  JS::PrivateValue(instance));
    474  // Set the super type vector
    475  setExtendedSlot(FunctionExtended::WASM_STV_SLOT,
    476                  JS::PrivateValue((void*)superTypeVector));
    477  // Set the unchecked entry slot
    478  setExtendedSlot(FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT,
    479                  JS::PrivateValue(uncheckedCallEntry));
    480 }
    481 
    482 void JSFunction::initWasmWithJitEntry(
    483    void** entry, wasm::Instance* instance,
    484    const wasm::SuperTypeVector* superTypeVector, void* uncheckedCallEntry) {
    485  MOZ_ASSERT(*entry);
    486  MOZ_ASSERT(isWasm());
    487  MOZ_ASSERT(!isWasmWithJitEntry());
    488 
    489  // Mark that we have a JIT entry, and initialize it
    490  setFlags(flags().setNativeJitEntry());
    491  setNativeJitInfoOrInterpretedScript(entry);
    492 
    493  // Set the instance
    494  setExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT,
    495                  JS::PrivateValue(instance));
    496  // Set the super type vector
    497  setExtendedSlot(FunctionExtended::WASM_STV_SLOT,
    498                  JS::PrivateValue((void*)superTypeVector));
    499  // Set the unchecked entry slot
    500  setExtendedSlot(FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT,
    501                  JS::PrivateValue(uncheckedCallEntry));
    502 
    503  MOZ_ASSERT(isWasmWithJitEntry());
    504 }
    505 
    506 void* JSFunction::wasmUncheckedCallEntry() const {
    507  MOZ_ASSERT(isWasm());
    508  return getExtendedSlot(FunctionExtended::WASM_FUNC_UNCHECKED_ENTRY_SLOT)
    509      .toPrivate();
    510 }
    511 
    512 void* JSFunction::wasmCheckedCallEntry() const {
    513  uint8_t* codeRangeBase;
    514  const wasm::CodeRange* codeRange;
    515  wasmInstance().code().funcCodeRange(wasmFuncIndex(), &codeRange,
    516                                      &codeRangeBase);
    517  return codeRangeBase + codeRange->funcCheckedCallEntry();
    518 }
    519 
    520 static bool fun_mayResolve(const JSAtomState& names, jsid id, JSObject*) {
    521  if (!id.isAtom()) {
    522    return false;
    523  }
    524 
    525  JSAtom* atom = id.toAtom();
    526  return atom == names.prototype || atom == names.length || atom == names.name;
    527 }
    528 
    529 bool JSFunction::getExplicitName(JSContext* cx,
    530                                 JS::MutableHandle<JSAtom*> name) {
    531  if (isAccessorWithLazyName()) {
    532    JSAtom* accessorName = getAccessorNameForLazy(cx);
    533    if (!accessorName) {
    534      return false;
    535    }
    536 
    537    name.set(accessorName);
    538    return true;
    539  }
    540 
    541  name.set(maybePartialExplicitName());
    542  return true;
    543 }
    544 
    545 bool JSFunction::getDisplayAtom(JSContext* cx,
    546                                JS::MutableHandle<JSAtom*> name) {
    547  if (isAccessorWithLazyName()) {
    548    JSAtom* accessorName = getAccessorNameForLazy(cx);
    549    if (!accessorName) {
    550      return false;
    551    }
    552 
    553    name.set(accessorName);
    554    return true;
    555  }
    556 
    557  name.set(maybePartialDisplayAtom());
    558  return true;
    559 }
    560 
    561 static JSAtom* NameToPrefixedFunctionName(JSContext* cx, JSString* nameStr,
    562                                          FunctionPrefixKind prefixKind) {
    563  MOZ_ASSERT(prefixKind != FunctionPrefixKind::None);
    564 
    565  StringBuilder sb(cx);
    566  if (prefixKind == FunctionPrefixKind::Get) {
    567    if (!sb.append("get ")) {
    568      return nullptr;
    569    }
    570  } else {
    571    if (!sb.append("set ")) {
    572      return nullptr;
    573    }
    574  }
    575  if (!sb.append(nameStr)) {
    576    return nullptr;
    577  }
    578  return sb.finishAtom();
    579 }
    580 
    581 static JSAtom* NameToFunctionName(JSContext* cx, HandleValue name,
    582                                  FunctionPrefixKind prefixKind) {
    583  MOZ_ASSERT(name.isString() || name.isNumeric());
    584 
    585  if (prefixKind == FunctionPrefixKind::None) {
    586    return ToAtom<CanGC>(cx, name);
    587  }
    588 
    589  JSString* nameStr = ToString(cx, name);
    590  if (!nameStr) {
    591    return nullptr;
    592  }
    593 
    594  return NameToPrefixedFunctionName(cx, nameStr, prefixKind);
    595 }
    596 
    597 JSAtom* JSFunction::getAccessorNameForLazy(JSContext* cx) {
    598  MOZ_ASSERT(isAccessorWithLazyName());
    599 
    600  JSAtom* name = NameToPrefixedFunctionName(
    601      cx, rawAtom(),
    602      isGetter() ? FunctionPrefixKind::Get : FunctionPrefixKind::Set);
    603  if (!name) {
    604    return nullptr;
    605  }
    606 
    607  setAtom(name);
    608  setFlags(flags().clearLazyAccessorName());
    609  return name;
    610 }
    611 
    612 static bool fun_resolve(JSContext* cx, HandleObject obj, HandleId id,
    613                        bool* resolvedp) {
    614  if (!id.isAtom()) {
    615    return true;
    616  }
    617 
    618  RootedFunction fun(cx, &obj->as<JSFunction>());
    619 
    620  if (id.isAtom(cx->names().prototype)) {
    621    if (!fun->needsPrototypeProperty()) {
    622      return true;
    623    }
    624 
    625    if (!ResolveInterpretedFunctionPrototype(cx, fun, id)) {
    626      return false;
    627    }
    628 
    629    *resolvedp = true;
    630    return true;
    631  }
    632 
    633  bool isLength = id.isAtom(cx->names().length);
    634  if (isLength || id.isAtom(cx->names().name)) {
    635    MOZ_ASSERT(!IsInternalFunctionObject(*obj));
    636 
    637    RootedValue v(cx);
    638 
    639    // Since f.length and f.name are configurable, they could be resolved
    640    // and then deleted:
    641    //     function f(x) {}
    642    //     assertEq(f.length, 1);
    643    //     delete f.length;
    644    //     assertEq(f.name, "f");
    645    //     delete f.name;
    646    // Afterwards, asking for f.length or f.name again will cause this
    647    // resolve hook to run again. Defining the property again the second
    648    // time through would be a bug.
    649    //     assertEq(f.length, 0);  // gets Function.prototype.length!
    650    //     assertEq(f.name, "");  // gets Function.prototype.name!
    651    // We use the RESOLVED_LENGTH and RESOLVED_NAME flags as a hack to prevent
    652    // this bug.
    653    if (isLength) {
    654      if (fun->hasResolvedLength()) {
    655        return true;
    656      }
    657 
    658      uint16_t len = 0;
    659      if (!JSFunction::getUnresolvedLength(cx, fun, &len)) {
    660        return false;
    661      }
    662      v.setInt32(len);
    663    } else {
    664      if (fun->hasResolvedName()) {
    665        return true;
    666      }
    667 
    668      JSAtom* name = fun->getUnresolvedName(cx);
    669      if (!name) {
    670        return false;
    671      }
    672      v.setString(name);
    673    }
    674 
    675    if (!NativeDefineDataProperty(cx, fun, id, v,
    676                                  JSPROP_READONLY | JSPROP_RESOLVING)) {
    677      return false;
    678    }
    679 
    680    if (isLength) {
    681      fun->setResolvedLength();
    682    } else {
    683      fun->setResolvedName();
    684    }
    685 
    686    *resolvedp = true;
    687    return true;
    688  }
    689 
    690  return true;
    691 }
    692 
    693 /* ES6 (04-25-16) 19.2.3.6 Function.prototype [ @@hasInstance ] */
    694 static bool fun_symbolHasInstance(JSContext* cx, unsigned argc, Value* vp) {
    695  CallArgs args = CallArgsFromVp(argc, vp);
    696 
    697  if (args.length() < 1) {
    698    args.rval().setBoolean(false);
    699    return true;
    700  }
    701 
    702  /* Step 1. */
    703  HandleValue func = args.thisv();
    704 
    705  // Primitives are non-callable and will always return false from
    706  // OrdinaryHasInstance.
    707  if (!func.isObject()) {
    708    args.rval().setBoolean(false);
    709    return true;
    710  }
    711 
    712  RootedObject obj(cx, &func.toObject());
    713 
    714  /* Step 2. */
    715  bool result;
    716  if (!OrdinaryHasInstance(cx, obj, args[0], &result)) {
    717    return false;
    718  }
    719 
    720  args.rval().setBoolean(result);
    721  return true;
    722 }
    723 
    724 /*
    725 * ES6 (4-25-16) 7.3.19 OrdinaryHasInstance
    726 */
    727 bool JS::OrdinaryHasInstance(JSContext* cx, HandleObject objArg, HandleValue v,
    728                             bool* bp) {
    729  AssertHeapIsIdle();
    730  cx->check(objArg, v);
    731 
    732  RootedObject obj(cx, objArg);
    733 
    734  /* Step 1. */
    735  if (!obj->isCallable()) {
    736    *bp = false;
    737    return true;
    738  }
    739 
    740  /* Step 2. */
    741  if (obj->is<BoundFunctionObject>()) {
    742    /* Steps 2a-b. */
    743    AutoCheckRecursionLimit recursion(cx);
    744    if (!recursion.check(cx)) {
    745      return false;
    746    }
    747    obj = obj->as<BoundFunctionObject>().getTarget();
    748    return InstanceofOperator(cx, obj, v, bp);
    749  }
    750 
    751  /* Step 3. */
    752  if (!v.isObject()) {
    753    *bp = false;
    754    return true;
    755  }
    756 
    757  /* Step 4. */
    758  RootedValue pval(cx);
    759  if (!GetProperty(cx, obj, obj, cx->names().prototype, &pval)) {
    760    return false;
    761  }
    762 
    763  /* Step 5. */
    764  if (pval.isPrimitive()) {
    765    /*
    766     * Throw a runtime error if instanceof is called on a function that
    767     * has a non-object as its .prototype value.
    768     */
    769    RootedValue val(cx, ObjectValue(*obj));
    770    ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, val, nullptr);
    771    return false;
    772  }
    773 
    774  /* Step 6. */
    775  RootedObject pobj(cx, &pval.toObject());
    776  bool isPrototype;
    777  if (!IsPrototypeOf(cx, pobj, &v.toObject(), &isPrototype)) {
    778    return false;
    779  }
    780  *bp = isPrototype;
    781  return true;
    782 }
    783 
    784 inline void JSFunction::trace(JSTracer* trc) {
    785  // Functions can be be marked as interpreted despite having no script yet at
    786  // some points when parsing, and can be lazy with no lazy script for
    787  // self-hosted code.
    788  MOZ_ASSERT(!getFixedSlot(NativeJitInfoOrInterpretedScriptSlot).isGCThing());
    789  if (isInterpreted() && hasBaseScript()) {
    790    if (BaseScript* script = baseScript()) {
    791      TraceManuallyBarrieredEdge(trc, &script, "JSFunction script");
    792      // Self-hosted scripts are shared with workers but are never relocated.
    793      // Skip unnecessary writes to prevent the possible data race.
    794      if (baseScript() != script) {
    795        HeapSlot& slot = getFixedSlotRef(NativeJitInfoOrInterpretedScriptSlot);
    796        slot.unbarrieredSet(JS::PrivateValue(script));
    797      }
    798    }
    799  }
    800  // wasm/asm.js exported functions need to keep WasmInstantObject alive,
    801  // access it via WASM_INSTANCE_SLOT extended slot.
    802  if (isAsmJSNative() || isWasm()) {
    803    const Value& v = getExtendedSlot(FunctionExtended::WASM_INSTANCE_SLOT);
    804    if (!v.isUndefined()) {
    805      auto* instance = static_cast<wasm::Instance*>(v.toPrivate());
    806      wasm::TraceInstanceEdge(trc, instance, "JSFunction instance");
    807    }
    808  }
    809 }
    810 
    811 static void fun_trace(JSTracer* trc, JSObject* obj) {
    812  obj->as<JSFunction>().trace(trc);
    813 }
    814 
    815 static JSObject* CreateFunctionConstructor(JSContext* cx, JSProtoKey key) {
    816  RootedObject functionProto(cx, &cx->global()->getPrototype(JSProto_Function));
    817 
    818  return NewFunctionWithProto(
    819      cx, Function, 1, FunctionFlags::NATIVE_CTOR, nullptr,
    820      Handle<PropertyName*>(cx->names().Function), functionProto,
    821      gc::AllocKind::FUNCTION, TenuredObject);
    822 }
    823 
    824 static bool FunctionPrototype(JSContext* cx, unsigned argc, Value* vp) {
    825  CallArgs args = CallArgsFromVp(argc, vp);
    826  args.rval().setUndefined();
    827  return true;
    828 }
    829 
    830 static JSObject* CreateFunctionPrototype(JSContext* cx, JSProtoKey key) {
    831  RootedObject objectProto(cx, &cx->global()->getPrototype(JSProto_Object));
    832 
    833  return NewFunctionWithProto(
    834      cx, FunctionPrototype, 0, FunctionFlags::NATIVE_FUN, nullptr,
    835      Handle<PropertyName*>(cx->names().empty_), objectProto,
    836      gc::AllocKind::FUNCTION, TenuredObject);
    837 }
    838 
    839 JSString* js::FunctionToStringCache::lookup(BaseScript* script) const {
    840  for (size_t i = 0; i < NumEntries; i++) {
    841    if (entries_[i].script == script) {
    842      return entries_[i].string;
    843    }
    844  }
    845  return nullptr;
    846 }
    847 
    848 void js::FunctionToStringCache::put(BaseScript* script, JSString* string) {
    849  for (size_t i = NumEntries - 1; i > 0; i--) {
    850    entries_[i] = entries_[i - 1];
    851  }
    852 
    853  entries_[0].set(script, string);
    854 }
    855 
    856 JSString* js::FunctionToString(JSContext* cx, HandleFunction fun,
    857                               bool isToSource) {
    858  if (IsAsmJSModule(fun)) {
    859    return AsmJSModuleToString(cx, fun, isToSource);
    860  }
    861  if (IsAsmJSFunction(fun)) {
    862    return AsmJSFunctionToString(cx, fun);
    863  }
    864 
    865  // Self-hosted built-ins should not expose their source code.
    866  bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin();
    867 
    868  // If we're in toSource mode, put parentheses around lambda functions so
    869  // that eval returns lambda, not function statement.
    870  bool addParentheses =
    871      haveSource && isToSource && (fun->isLambda() && !fun->isArrow());
    872 
    873  if (haveSource) {
    874    if (!ScriptSource::loadSource(cx, fun->baseScript()->scriptSource(),
    875                                  &haveSource)) {
    876      return nullptr;
    877    }
    878  }
    879 
    880  // Fast path for the common case, to avoid StringBuilder overhead.
    881  if (!addParentheses && haveSource) {
    882    FunctionToStringCache& cache = cx->zone()->functionToStringCache();
    883    if (JSString* str = cache.lookup(fun->baseScript())) {
    884      return str;
    885    }
    886 
    887    BaseScript* script = fun->baseScript();
    888    size_t start = script->toStringStart();
    889    size_t end = script->toStringEnd();
    890    JSString* str =
    891        (end - start <= ScriptSource::SourceDeflateLimit)
    892            ? script->scriptSource()->substring(cx, start, end)
    893            : script->scriptSource()->substringDontDeflate(cx, start, end);
    894    if (!str) {
    895      return nullptr;
    896    }
    897 
    898    cache.put(fun->baseScript(), str);
    899    return str;
    900  }
    901 
    902  JSStringBuilder out(cx);
    903  if (addParentheses) {
    904    if (!out.append('(')) {
    905      return nullptr;
    906    }
    907  }
    908 
    909  if (haveSource) {
    910    if (!fun->baseScript()->appendSourceDataForToString(cx, out)) {
    911      return nullptr;
    912    }
    913  } else if (!isToSource) {
    914    // For the toString() output the source representation must match
    915    // NativeFunction when no source text is available.
    916    //
    917    // NativeFunction:
    918    //   function PropertyName[~Yield,~Await]opt (
    919    //      FormalParameters[~Yield,~Await] ) { [native code] }
    920    //
    921    // Additionally, if |fun| is a well-known intrinsic object and is not
    922    // identified as an anonymous function, the portion of the returned
    923    // string that would be matched by IdentifierName must be the initial
    924    // value of the name property of |fun|.
    925 
    926    auto hasGetterOrSetterPrefix = [](JSAtom* name) {
    927      auto hasGetterOrSetterPrefix = [](const auto* chars) {
    928        return (chars[0] == 'g' || chars[0] == 's') && chars[1] == 'e' &&
    929               chars[2] == 't' && chars[3] == ' ';
    930      };
    931 
    932      JS::AutoCheckCannotGC nogc;
    933      return name->length() >= 4 &&
    934             (name->hasLatin1Chars()
    935                  ? hasGetterOrSetterPrefix(name->latin1Chars(nogc))
    936                  : hasGetterOrSetterPrefix(name->twoByteChars(nogc)));
    937    };
    938 
    939    if (!out.append("function")) {
    940      return nullptr;
    941    }
    942 
    943    // We don't want to fully parse the function's name here because of
    944    // performance reasons, so only append the name if we're confident it
    945    // can be matched as the 'PropertyName' grammar production.
    946    if (fun->maybePartialExplicitName() &&
    947        (fun->kind() == FunctionFlags::NormalFunction ||
    948         (fun->isBuiltinNative() && (fun->kind() == FunctionFlags::Getter ||
    949                                     fun->kind() == FunctionFlags::Setter)) ||
    950         fun->kind() == FunctionFlags::Wasm ||
    951         fun->kind() == FunctionFlags::ClassConstructor)) {
    952      if (!out.append(' ')) {
    953        return nullptr;
    954      }
    955 
    956      // Built-in getters or setters are classified as one of
    957      // NormalFunction, Getter, or Setter. Strip any leading "get " or "set "
    958      // if present.
    959      JSAtom* name = fun->maybePartialExplicitName();
    960      size_t offset = hasGetterOrSetterPrefix(name) ? 4 : 0;
    961      if (!out.appendSubstring(name, offset, name->length() - offset)) {
    962        return nullptr;
    963      }
    964    }
    965 
    966    if (!out.append("() {\n    [native code]\n}")) {
    967      return nullptr;
    968    }
    969  } else {
    970    if (fun->isAsync()) {
    971      if (!out.append("async ")) {
    972        return nullptr;
    973      }
    974    }
    975 
    976    if (!fun->isArrow()) {
    977      if (!out.append("function")) {
    978        return nullptr;
    979      }
    980 
    981      if (fun->isGenerator()) {
    982        if (!out.append('*')) {
    983          return nullptr;
    984        }
    985      }
    986    }
    987 
    988    JS::Rooted<JSAtom*> name(cx);
    989    if (!fun->getExplicitName(cx, &name)) {
    990      return nullptr;
    991    }
    992 
    993    if (name) {
    994      if (!out.append(' ')) {
    995        return nullptr;
    996      }
    997      if (!out.append(name)) {
    998        return nullptr;
    999      }
   1000    }
   1001 
   1002    if (!out.append("() {\n    [native code]\n}")) {
   1003      return nullptr;
   1004    }
   1005  }
   1006 
   1007  if (addParentheses) {
   1008    if (!out.append(')')) {
   1009      return nullptr;
   1010    }
   1011  }
   1012 
   1013  return out.finishString();
   1014 }
   1015 
   1016 JSString* js::fun_toStringHelper(JSContext* cx, HandleObject obj,
   1017                                 bool isToSource) {
   1018  if (!obj->is<JSFunction>()) {
   1019    if (JSFunToStringOp op = obj->getOpsFunToString()) {
   1020      return op(cx, obj, isToSource);
   1021    }
   1022 
   1023    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1024                              JSMSG_INCOMPATIBLE_PROTO, "Function", "toString",
   1025                              "object");
   1026    return nullptr;
   1027  }
   1028 
   1029  return FunctionToString(cx, obj.as<JSFunction>(), isToSource);
   1030 }
   1031 
   1032 bool js::fun_toString(JSContext* cx, unsigned argc, Value* vp) {
   1033  CallArgs args = CallArgsFromVp(argc, vp);
   1034  MOZ_ASSERT(IsFunctionObject(args.calleev()));
   1035 
   1036  RootedObject obj(cx, ToObject(cx, args.thisv()));
   1037  if (!obj) {
   1038    return false;
   1039  }
   1040 
   1041  JSString* str = fun_toStringHelper(cx, obj, /* isToSource = */ false);
   1042  if (!str) {
   1043    return false;
   1044  }
   1045 
   1046  args.rval().setString(str);
   1047  return true;
   1048 }
   1049 
   1050 static bool fun_toSource(JSContext* cx, unsigned argc, Value* vp) {
   1051  CallArgs args = CallArgsFromVp(argc, vp);
   1052  MOZ_ASSERT(IsFunctionObject(args.calleev()));
   1053 
   1054  RootedObject obj(cx, ToObject(cx, args.thisv()));
   1055  if (!obj) {
   1056    return false;
   1057  }
   1058 
   1059  RootedString str(cx);
   1060  if (obj->isCallable()) {
   1061    str = fun_toStringHelper(cx, obj, /* isToSource = */ true);
   1062  } else {
   1063    str = ObjectToSource(cx, obj);
   1064  }
   1065  if (!str) {
   1066    return false;
   1067  }
   1068 
   1069  args.rval().setString(str);
   1070  return true;
   1071 }
   1072 
   1073 bool js::fun_call(JSContext* cx, unsigned argc, Value* vp) {
   1074  CallArgs args = CallArgsFromVp(argc, vp);
   1075 
   1076  HandleValue func = args.thisv();
   1077 
   1078  // We don't need to do this -- Call would do it for us -- but the error
   1079  // message is *much* better if we do this here.  (Without this,
   1080  // JSDVG_SEARCH_STACK tries to decompile |func| as if it were |this| in
   1081  // the scripted caller's frame -- so for example
   1082  //
   1083  //   Function.prototype.call.call({});
   1084  //
   1085  // would identify |{}| as |this| as being the result of evaluating
   1086  // |Function.prototype.call| and would conclude, "Function.prototype.call
   1087  // is not a function".  Grotesque.)
   1088  if (!IsCallable(func)) {
   1089    ReportIncompatibleMethod(cx, args, &FunctionClass);
   1090    return false;
   1091  }
   1092 
   1093  size_t argCount = args.length();
   1094  if (argCount > 0) {
   1095    argCount--;  // strip off provided |this|
   1096  }
   1097 
   1098  InvokeArgs iargs(cx);
   1099  if (!iargs.init(cx, argCount)) {
   1100    return false;
   1101  }
   1102 
   1103  for (size_t i = 0; i < argCount; i++) {
   1104    iargs[i].set(args[i + 1]);
   1105  }
   1106 
   1107  return Call(cx, func, args.get(0), iargs, args.rval(), CallReason::FunCall);
   1108 }
   1109 
   1110 // ES5 15.3.4.3
   1111 bool js::fun_apply(JSContext* cx, unsigned argc, Value* vp) {
   1112  CallArgs args = CallArgsFromVp(argc, vp);
   1113 
   1114  // Step 1.
   1115  //
   1116  // Note that we must check callability here, not at actual call time,
   1117  // because extracting argument values from the provided arraylike might
   1118  // have side effects or throw an exception.
   1119  HandleValue fval = args.thisv();
   1120  if (!IsCallable(fval)) {
   1121    ReportIncompatibleMethod(cx, args, &FunctionClass);
   1122    return false;
   1123  }
   1124 
   1125  // Step 2.
   1126  if (args.length() < 2 || args[1].isNullOrUndefined()) {
   1127    return fun_call(cx, (args.length() > 0) ? 1 : 0, vp);
   1128  }
   1129 
   1130  // Step 3.
   1131  if (!args[1].isObject()) {
   1132    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1133                              JSMSG_BAD_APPLY_ARGS, "apply");
   1134    return false;
   1135  }
   1136 
   1137  // Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in
   1138  // original version of ES5).
   1139  RootedObject aobj(cx, &args[1].toObject());
   1140  uint64_t length;
   1141  if (!GetLengthProperty(cx, aobj, &length)) {
   1142    return false;
   1143  }
   1144 
   1145  // Step 6.
   1146  InvokeArgs args2(cx);
   1147  if (!args2.init(cx, length)) {
   1148    return false;
   1149  }
   1150 
   1151  MOZ_ASSERT(length <= ARGS_LENGTH_MAX);
   1152 
   1153  // Steps 7-8.
   1154  if (!GetElements(cx, aobj, length, args2.array())) {
   1155    return false;
   1156  }
   1157 
   1158  // Step 9.
   1159  return Call(cx, fval, args[0], args2, args.rval(), CallReason::FunCall);
   1160 }
   1161 
   1162 static const JSFunctionSpec function_methods[] = {
   1163    JS_FN("toSource", fun_toSource, 0, 0),
   1164    JS_FN("toString", fun_toString, 0, 0),
   1165    JS_FN("apply", fun_apply, 2, 0),
   1166    JS_FN("call", fun_call, 1, 0),
   1167    JS_INLINABLE_FN("bind", BoundFunctionObject::functionBind, 1, 0,
   1168                    FunctionBind),
   1169    JS_SYM_FN(hasInstance, fun_symbolHasInstance, 1,
   1170              JSPROP_READONLY | JSPROP_PERMANENT),
   1171    JS_FS_END,
   1172 };
   1173 
   1174 static const JSClassOps JSFunctionClassOps = {
   1175    nullptr,         // addProperty
   1176    nullptr,         // delProperty
   1177    fun_enumerate,   // enumerate
   1178    nullptr,         // newEnumerate
   1179    fun_resolve,     // resolve
   1180    fun_mayResolve,  // mayResolve
   1181    nullptr,         // finalize
   1182    nullptr,         // call
   1183    nullptr,         // construct
   1184    fun_trace,       // trace
   1185 };
   1186 
   1187 static const ClassSpec JSFunctionClassSpec = {
   1188    CreateFunctionConstructor, CreateFunctionPrototype, nullptr, nullptr,
   1189    function_methods,          function_properties,
   1190 };
   1191 
   1192 const JSClass js::FunctionClass = {
   1193    "Function",
   1194    JSCLASS_HAS_CACHED_PROTO(JSProto_Function) |
   1195        JSCLASS_HAS_RESERVED_SLOTS(JSFunction::SlotCount),
   1196    &JSFunctionClassOps,
   1197    &JSFunctionClassSpec,
   1198 };
   1199 
   1200 const JSClass js::ExtendedFunctionClass = {
   1201    "Function",
   1202    JSCLASS_HAS_CACHED_PROTO(JSProto_Function) |
   1203        JSCLASS_HAS_RESERVED_SLOTS(FunctionExtended::SlotCount),
   1204    &JSFunctionClassOps,
   1205    &JSFunctionClassSpec,
   1206 };
   1207 
   1208 const JSClass* const js::FunctionClassPtr = &FunctionClass;
   1209 const JSClass* const js::FunctionExtendedClassPtr = &ExtendedFunctionClass;
   1210 
   1211 bool JSFunction::isDerivedClassConstructor() const {
   1212  bool derived = hasBaseScript() && baseScript()->isDerivedClassConstructor();
   1213  MOZ_ASSERT_IF(derived, isClassConstructor());
   1214  return derived;
   1215 }
   1216 
   1217 bool JSFunction::isSyntheticFunction() const {
   1218  bool synthetic = hasBaseScript() && baseScript()->isSyntheticFunction();
   1219  MOZ_ASSERT_IF(synthetic, isMethod());
   1220  return synthetic;
   1221 }
   1222 
   1223 /* static */
   1224 bool JSFunction::delazifyLazilyInterpretedFunction(JSContext* cx,
   1225                                                   HandleFunction fun) {
   1226  MOZ_ASSERT(fun->hasBaseScript());
   1227  MOZ_ASSERT(cx->compartment() == fun->compartment());
   1228 
   1229  // The function must be same-compartment but might be cross-realm. Make sure
   1230  // the script is created in the function's realm.
   1231  AutoRealm ar(cx, fun);
   1232 
   1233  Rooted<BaseScript*> lazy(cx, fun->baseScript());
   1234  RootedFunction canonicalFun(cx, lazy->function());
   1235 
   1236  // If this function is non-canonical, then use the canonical function first
   1237  // to get the delazified script. This may result in calling this method
   1238  // again on the canonical function. This ensures the canonical function is
   1239  // always non-lazy if any of the clones are non-lazy.
   1240  if (fun != canonicalFun) {
   1241    JSScript* script = JSFunction::getOrCreateScript(cx, canonicalFun);
   1242    if (!script) {
   1243      return false;
   1244    }
   1245 
   1246    // Delazifying the canonical function should naturally make us non-lazy
   1247    // because we share a BaseScript with the canonical function.
   1248    MOZ_ASSERT(fun->hasBytecode());
   1249    return true;
   1250  }
   1251 
   1252  // Finally, compile the script if it really doesn't exist.
   1253  AutoReportFrontendContext fc(cx);
   1254  if (!frontend::DelazifyCanonicalScriptedFunction(cx, &fc, fun)) {
   1255    // The frontend shouldn't fail after linking the function and the
   1256    // non-lazy script together.
   1257    MOZ_ASSERT(fun->baseScript() == lazy);
   1258    MOZ_ASSERT(lazy->isReadyForDelazification());
   1259    return false;
   1260  }
   1261 
   1262  return true;
   1263 }
   1264 
   1265 /* static */
   1266 bool JSFunction::delazifySelfHostedLazyFunction(JSContext* cx,
   1267                                                js::HandleFunction fun) {
   1268  MOZ_ASSERT(cx->compartment() == fun->compartment());
   1269 
   1270  // The function must be same-compartment but might be cross-realm. Make sure
   1271  // the script is created in the function's realm.
   1272  AutoRealm ar(cx, fun);
   1273 
   1274  /* Lazily cloned self-hosted script. */
   1275  MOZ_ASSERT(fun->isSelfHostedBuiltin());
   1276  Rooted<PropertyName*> funName(cx, GetClonedSelfHostedFunctionName(fun));
   1277  if (!funName) {
   1278    return false;
   1279  }
   1280  return cx->runtime()->delazifySelfHostedFunction(cx, funName, fun);
   1281 }
   1282 
   1283 void JSFunction::maybeRelazify(JSRuntime* rt) {
   1284  MOZ_ASSERT(!isIncomplete(), "Cannot relazify incomplete functions");
   1285 
   1286  // Don't relazify functions in compartments that are active.
   1287  Realm* realm = this->realm();
   1288  if (!rt->allowRelazificationForTesting) {
   1289    if (realm->compartment()->gcState.hasEnteredRealm) {
   1290      return;
   1291    }
   1292 
   1293    MOZ_ASSERT(!realm->hasBeenEnteredIgnoringJit());
   1294  }
   1295 
   1296  // Don't relazify if the realm is being debugged. The debugger side-tables
   1297  // such as the set of active breakpoints require bytecode to exist.
   1298  if (realm->isDebuggee()) {
   1299    return;
   1300  }
   1301 
   1302  // Don't relazify if we are collecting coverage so that we do not lose count
   1303  // information.
   1304  if (coverage::IsLCovEnabled()) {
   1305    return;
   1306  }
   1307 
   1308  // Check the script's eligibility.
   1309  JSScript* script = nonLazyScript();
   1310  if (!script->allowRelazify()) {
   1311    return;
   1312  }
   1313  MOZ_ASSERT(script->isRelazifiable());
   1314 
   1315  // There must not be any JIT code attached since the relazification process
   1316  // does not know how to discard it. In general, the GC should discard most JIT
   1317  // code before attempting relazification.
   1318  if (script->hasJitScript()) {
   1319    return;
   1320  }
   1321 
   1322  if (isSelfHostedBuiltin()) {
   1323    gc::PreWriteBarrier(script);
   1324    initSelfHostedLazyScript(&rt->selfHostedLazyScript.ref());
   1325  } else {
   1326    script->relazify(rt);
   1327  }
   1328 }
   1329 
   1330 js::GeneratorKind JSFunction::clonedSelfHostedGeneratorKind() const {
   1331  MOZ_ASSERT(hasSelfHostedLazyScript());
   1332 
   1333  // This is a lazy clone of a self-hosted builtin. It has no BaseScript, and
   1334  // `this->flags_` does not contain the generator kind. Consult the
   1335  // implementation in the self-hosting realm, which has a BaseScript.
   1336  MOZ_RELEASE_ASSERT(isExtended());
   1337  PropertyName* name = GetClonedSelfHostedFunctionName(this);
   1338  return runtimeFromMainThread()->getSelfHostedFunctionGeneratorKind(name);
   1339 }
   1340 
   1341 // ES2018 draft rev 2aea8f3e617b49df06414eb062ab44fad87661d3
   1342 // 19.2.1.1.1 CreateDynamicFunction( constructor, newTarget, kind, args )
   1343 static bool CreateDynamicFunction(JSContext* cx, const CallArgs& args,
   1344                                  GeneratorKind generatorKind,
   1345                                  FunctionAsyncKind asyncKind) {
   1346  using namespace frontend;
   1347 
   1348  // Steps 1-5.
   1349  bool isGenerator = generatorKind == GeneratorKind::Generator;
   1350  bool isAsync = asyncKind == FunctionAsyncKind::AsyncFunction;
   1351 
   1352  RootedScript maybeScript(cx);
   1353  const char* filename;
   1354  uint32_t lineno;
   1355  bool mutedErrors;
   1356  uint32_t pcOffset;
   1357  DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno,
   1358                                       &pcOffset, &mutedErrors);
   1359 
   1360  const char* introductionType = "Function";
   1361  if (isAsync) {
   1362    if (isGenerator) {
   1363      introductionType = "AsyncGenerator";
   1364    } else {
   1365      introductionType = "AsyncFunction";
   1366    }
   1367  } else if (isGenerator) {
   1368    introductionType = "GeneratorFunction";
   1369  }
   1370 
   1371  const char* introducerFilename = filename;
   1372  if (maybeScript && maybeScript->scriptSource()->introducerFilename()) {
   1373    introducerFilename = maybeScript->scriptSource()->introducerFilename();
   1374  }
   1375 
   1376  CompileOptions options(cx);
   1377  options.setMutedErrors(mutedErrors)
   1378      .setFileAndLine(filename, 1)
   1379      .setNoScriptRval(false)
   1380      .setIntroductionInfo(introducerFilename, introductionType, lineno,
   1381                           pcOffset)
   1382      .setDeferDebugMetadata();
   1383 
   1384  JSStringBuilder sb(cx);
   1385 
   1386  if (isAsync) {
   1387    if (!sb.append("async ")) {
   1388      return false;
   1389    }
   1390  }
   1391  if (!sb.append("function")) {
   1392    return false;
   1393  }
   1394  if (isGenerator) {
   1395    if (!sb.append('*')) {
   1396      return false;
   1397    }
   1398  }
   1399 
   1400  if (!sb.append(" anonymous(")) {
   1401    return false;
   1402  }
   1403 
   1404  JS::RootedVector<JSString*> parameterStrings(cx);
   1405  JS::RootedVector<Value> parameterArgs(cx);
   1406  if (args.length() > 1) {
   1407    RootedString str(cx);
   1408 
   1409    // Steps 10, 14.d.
   1410    unsigned n = args.length() - 1;
   1411    if (!parameterStrings.reserve(n) || !parameterArgs.reserve(n)) {
   1412      return false;
   1413    }
   1414 
   1415    for (unsigned i = 0; i < n; i++) {
   1416      if (!parameterArgs.append(args[i])) {
   1417        return false;
   1418      }
   1419 
   1420      // Steps 14.a-b, 14.d.i-ii.
   1421      str = ToString<CanGC>(cx, args[i]);
   1422      if (!str) {
   1423        return false;
   1424      }
   1425 
   1426      if (!parameterStrings.append(str)) {
   1427        return false;
   1428      }
   1429 
   1430      // Steps 14.b, 14.d.iii.
   1431      if (!sb.append(str)) {
   1432        return false;
   1433      }
   1434 
   1435      if (i < args.length() - 2) {
   1436        // Step 14.d.iii.
   1437        if (!sb.append(',')) {
   1438          return false;
   1439        }
   1440      }
   1441    }
   1442  }
   1443 
   1444  if (!sb.append('\n')) {
   1445    return false;
   1446  }
   1447 
   1448  // Remember the position of ")".
   1449  Maybe<uint32_t> parameterListEnd = Some(uint32_t(sb.length()));
   1450  static_assert(FunctionConstructorMedialSigils[0] == ')');
   1451 
   1452  if (!sb.append(FunctionConstructorMedialSigils.data(),
   1453                 FunctionConstructorMedialSigils.length())) {
   1454    return false;
   1455  }
   1456 
   1457  JS::RootedValue bodyArg(cx);
   1458  RootedString bodyString(cx);
   1459  if (args.length() > 0) {
   1460    // Steps 13, 14.e, 15.
   1461    bodyArg = args[args.length() - 1];
   1462    bodyString = ToString<CanGC>(cx, bodyArg);
   1463    if (!bodyString || !sb.append(bodyString)) {
   1464      return false;
   1465    }
   1466  }
   1467 
   1468  if (!sb.append(FunctionConstructorFinalBrace.data(),
   1469                 FunctionConstructorFinalBrace.length())) {
   1470    return false;
   1471  }
   1472 
   1473  // The parser only accepts two byte strings.
   1474  if (!sb.ensureTwoByteChars()) {
   1475    return false;
   1476  }
   1477 
   1478  RootedString functionText(cx, sb.finishString());
   1479  if (!functionText) {
   1480    return false;
   1481  }
   1482 
   1483  // Block this call if security callbacks forbid it.
   1484  bool canCompileStrings = cx->bypassCSPForDebugger;
   1485 
   1486  if (!canCompileStrings &&
   1487      !cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, functionText,
   1488                                   JS::CompilationType::Function,
   1489                                   parameterStrings, bodyString, parameterArgs,
   1490                                   bodyArg, &canCompileStrings)) {
   1491    return false;
   1492  }
   1493  if (!canCompileStrings) {
   1494    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1495                              JSMSG_CSP_BLOCKED_FUNCTION);
   1496    return false;
   1497  }
   1498 
   1499  // Steps 7.a-b, 8.a-b, 9.a-b, 16-28.
   1500  AutoStableStringChars linearChars(cx);
   1501  if (!linearChars.initTwoByte(cx, functionText)) {
   1502    return false;
   1503  }
   1504 
   1505  SourceText<char16_t> srcBuf;
   1506  if (!srcBuf.initMaybeBorrowed(cx, linearChars)) {
   1507    return false;
   1508  }
   1509 
   1510  FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Expression;
   1511 
   1512  RootedFunction fun(cx);
   1513  JSProtoKey protoKey;
   1514  if (isAsync) {
   1515    if (isGenerator) {
   1516      fun = CompileStandaloneAsyncGenerator(cx, options, srcBuf,
   1517                                            parameterListEnd, syntaxKind);
   1518      protoKey = JSProto_AsyncGeneratorFunction;
   1519    } else {
   1520      fun = CompileStandaloneAsyncFunction(cx, options, srcBuf,
   1521                                           parameterListEnd, syntaxKind);
   1522      protoKey = JSProto_AsyncFunction;
   1523    }
   1524  } else {
   1525    if (isGenerator) {
   1526      fun = CompileStandaloneGenerator(cx, options, srcBuf, parameterListEnd,
   1527                                       syntaxKind);
   1528      protoKey = JSProto_GeneratorFunction;
   1529    } else {
   1530      fun = CompileStandaloneFunction(cx, options, srcBuf, parameterListEnd,
   1531                                      syntaxKind);
   1532      protoKey = JSProto_Function;
   1533    }
   1534  }
   1535  if (!fun) {
   1536    return false;
   1537  }
   1538 
   1539  RootedValue undefValue(cx);
   1540  RootedScript funScript(cx, JS_GetFunctionScript(cx, fun));
   1541  JS::InstantiateOptions instantiateOptions(options);
   1542  if (funScript &&
   1543      !UpdateDebugMetadata(cx, funScript, instantiateOptions, undefValue,
   1544                           nullptr, maybeScript, maybeScript)) {
   1545    return false;
   1546  }
   1547 
   1548  if (fun->isInterpreted()) {
   1549    fun->initEnvironment(&cx->global()->lexicalEnvironment());
   1550  }
   1551 
   1552  // Steps 6, 29.
   1553  RootedObject proto(cx);
   1554  if (!GetPrototypeFromBuiltinConstructor(cx, args, protoKey, &proto)) {
   1555    return false;
   1556  }
   1557 
   1558  // Steps 7.d, 8.d (implicit).
   1559  // Call SetPrototype if an explicit prototype was given.
   1560  if (proto && !SetPrototype(cx, fun, proto)) {
   1561    return false;
   1562  }
   1563 
   1564  // Step 38.
   1565  args.rval().setObject(*fun);
   1566  return true;
   1567 }
   1568 
   1569 bool js::Function(JSContext* cx, unsigned argc, Value* vp) {
   1570  CallArgs args = CallArgsFromVp(argc, vp);
   1571  return CreateDynamicFunction(cx, args, GeneratorKind::NotGenerator,
   1572                               FunctionAsyncKind::SyncFunction);
   1573 }
   1574 
   1575 bool js::Generator(JSContext* cx, unsigned argc, Value* vp) {
   1576  CallArgs args = CallArgsFromVp(argc, vp);
   1577  return CreateDynamicFunction(cx, args, GeneratorKind::Generator,
   1578                               FunctionAsyncKind::SyncFunction);
   1579 }
   1580 
   1581 bool js::AsyncFunctionConstructor(JSContext* cx, unsigned argc, Value* vp) {
   1582  CallArgs args = CallArgsFromVp(argc, vp);
   1583  return CreateDynamicFunction(cx, args, GeneratorKind::NotGenerator,
   1584                               FunctionAsyncKind::AsyncFunction);
   1585 }
   1586 
   1587 bool js::AsyncGeneratorConstructor(JSContext* cx, unsigned argc, Value* vp) {
   1588  CallArgs args = CallArgsFromVp(argc, vp);
   1589  return CreateDynamicFunction(cx, args, GeneratorKind::Generator,
   1590                               FunctionAsyncKind::AsyncFunction);
   1591 }
   1592 
   1593 bool JSFunction::isBuiltinFunctionConstructor() {
   1594  return maybeNative() == Function || maybeNative() == Generator;
   1595 }
   1596 
   1597 bool JSFunction::needsExtraBodyVarEnvironment() const {
   1598  if (isNativeFun()) {
   1599    return false;
   1600  }
   1601 
   1602  if (!nonLazyScript()->functionHasExtraBodyVarScope()) {
   1603    return false;
   1604  }
   1605 
   1606  return nonLazyScript()->functionExtraBodyVarScope()->hasEnvironment();
   1607 }
   1608 
   1609 bool JSFunction::needsNamedLambdaEnvironment() const {
   1610  if (!isNamedLambda()) {
   1611    return false;
   1612  }
   1613 
   1614  LexicalScope* scope = nonLazyScript()->maybeNamedLambdaScope();
   1615  if (!scope) {
   1616    return false;
   1617  }
   1618 
   1619  return scope->hasEnvironment();
   1620 }
   1621 
   1622 bool JSFunction::needsCallObject() const {
   1623  if (isNativeFun()) {
   1624    return false;
   1625  }
   1626 
   1627  MOZ_ASSERT(hasBytecode());
   1628 
   1629  // Note: this should be kept in sync with
   1630  // FunctionBox::needsCallObjectRegardlessOfBindings().
   1631  MOZ_ASSERT_IF(
   1632      baseScript()->funHasExtensibleScope() || isGenerator() || isAsync(),
   1633      nonLazyScript()->bodyScope()->hasEnvironment());
   1634 
   1635  return nonLazyScript()->bodyScope()->hasEnvironment();
   1636 }
   1637 
   1638 #if defined(DEBUG) || defined(JS_JITSPEW)
   1639 void JSFunction::dumpOwnFields(js::JSONPrinter& json) const {
   1640  if (maybePartialDisplayAtom()) {
   1641    js::GenericPrinter& out =
   1642        json.beginStringProperty("maybePartialDisplayAtom");
   1643    maybePartialDisplayAtom()->dumpPropertyName(out);
   1644    json.endStringProperty();
   1645  }
   1646 
   1647  if (hasBaseScript()) {
   1648    js::GenericPrinter& out = json.beginStringProperty("baseScript");
   1649    baseScript()->dumpStringContent(out);
   1650    json.endStringProperty();
   1651  }
   1652 
   1653  json.property("nargs", nargs());
   1654 
   1655  json.beginInlineListProperty("flags");
   1656  DumpFunctionFlagsItems(json, flags());
   1657  json.endInlineList();
   1658 
   1659  if (isNativeFun()) {
   1660    json.formatProperty("native", "0x%p", native());
   1661    if (hasJitInfo()) {
   1662      json.formatProperty("jitInfo", "0x%p", jitInfo());
   1663    }
   1664  }
   1665 }
   1666 
   1667 void JSFunction::dumpOwnStringContent(js::GenericPrinter& out) const {
   1668  if (maybePartialDisplayAtom() && maybePartialDisplayAtom()->length() > 0) {
   1669    maybePartialDisplayAtom()->dumpPropertyName(out);
   1670  } else {
   1671    out.put("(anonymous)");
   1672  }
   1673 
   1674  if (hasBaseScript()) {
   1675    out.put(" (");
   1676    baseScript()->dumpStringContent(out);
   1677    out.put(")");
   1678  }
   1679 }
   1680 #endif
   1681 
   1682 #ifdef DEBUG
   1683 static JSObject* SkipEnvironmentObjects(JSObject* env) {
   1684  if (!env) {
   1685    return nullptr;
   1686  }
   1687  while (env->is<EnvironmentObject>()) {
   1688    env = &env->as<EnvironmentObject>().enclosingEnvironment();
   1689  }
   1690  return env;
   1691 }
   1692 
   1693 static bool NewFunctionEnvironmentIsWellFormed(JSContext* cx,
   1694                                               HandleObject env) {
   1695  // Assert that the terminating environment is null, global, or a debug
   1696  // scope proxy. All other cases of polluting global scope behavior are
   1697  // handled by EnvironmentObjects (viz. non-syntactic DynamicWithObject and
   1698  // NonSyntacticVariablesObject).
   1699  JSObject* terminatingEnv = SkipEnvironmentObjects(env);
   1700  return !terminatingEnv || terminatingEnv == cx->global() ||
   1701         terminatingEnv->is<DebugEnvironmentProxy>();
   1702 }
   1703 #endif
   1704 
   1705 static inline const JSClass* FunctionClassForAllocKind(
   1706    gc::AllocKind allocKind) {
   1707  return (allocKind == gc::AllocKind::FUNCTION) ? FunctionClassPtr
   1708                                                : FunctionExtendedClassPtr;
   1709 }
   1710 
   1711 static void AssertClassMatchesAllocKind(const JSClass* clasp,
   1712                                        gc::AllocKind kind) {
   1713 #ifdef DEBUG
   1714  if (kind == gc::AllocKind::FUNCTION_EXTENDED) {
   1715    MOZ_ASSERT(clasp == FunctionExtendedClassPtr);
   1716  } else {
   1717    MOZ_ASSERT(kind == gc::AllocKind::FUNCTION);
   1718    MOZ_ASSERT(clasp == FunctionClassPtr);
   1719  }
   1720 #endif
   1721 }
   1722 
   1723 static SharedShape* GetFunctionShape(JSContext* cx, const JSClass* clasp,
   1724                                     JSObject* proto, gc::AllocKind allocKind) {
   1725  AssertClassMatchesAllocKind(clasp, allocKind);
   1726 
   1727  size_t nfixed = GetGCKindSlots(allocKind);
   1728  return SharedShape::getInitialShape(
   1729      cx, clasp, cx->realm(), TaggedProto(proto), nfixed, ObjectFlags());
   1730 }
   1731 
   1732 SharedShape* GlobalObject::createFunctionShapeWithDefaultProto(JSContext* cx,
   1733                                                               bool extended) {
   1734  GlobalObjectData& data = cx->global()->data();
   1735  GCPtr<SharedShape*>& shapeRef =
   1736      extended ? data.extendedFunctionShapeWithDefaultProto
   1737               : data.functionShapeWithDefaultProto;
   1738  MOZ_ASSERT(!shapeRef);
   1739 
   1740  RootedObject proto(cx,
   1741                     GlobalObject::getOrCreatePrototype(cx, JSProto_Function));
   1742  if (!proto) {
   1743    return nullptr;
   1744  }
   1745 
   1746  // Creating %Function.prototype% can end up initializing the shape.
   1747  if (shapeRef) {
   1748    return shapeRef;
   1749  }
   1750 
   1751  gc::AllocKind allocKind =
   1752      extended ? gc::AllocKind::FUNCTION_EXTENDED : gc::AllocKind::FUNCTION;
   1753  const JSClass* clasp = FunctionClassForAllocKind(allocKind);
   1754 
   1755  SharedShape* shape = GetFunctionShape(cx, clasp, proto, allocKind);
   1756  if (!shape) {
   1757    return nullptr;
   1758  }
   1759 
   1760  shapeRef.init(shape);
   1761  return shape;
   1762 }
   1763 
   1764 JSFunction* js::NewFunctionWithProto(
   1765    JSContext* cx, Native native, unsigned nargs, FunctionFlags flags,
   1766    HandleObject enclosingEnv, Handle<JSAtom*> atom, HandleObject proto,
   1767    gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
   1768    NewObjectKind newKind /* = GenericObject */) {
   1769  MOZ_ASSERT(allocKind == gc::AllocKind::FUNCTION ||
   1770             allocKind == gc::AllocKind::FUNCTION_EXTENDED);
   1771  MOZ_ASSERT_IF(native, !enclosingEnv);
   1772  MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
   1773 
   1774  // NOTE: Keep this in sync with `CreateFunctionFast` in Stencil.cpp
   1775 
   1776  const JSClass* clasp = FunctionClassForAllocKind(allocKind);
   1777 
   1778  Rooted<SharedShape*> shape(cx);
   1779  if (!proto) {
   1780    bool extended = (allocKind == gc::AllocKind::FUNCTION_EXTENDED);
   1781    shape = GlobalObject::getFunctionShapeWithDefaultProto(cx, extended);
   1782  } else {
   1783    shape = GetFunctionShape(cx, clasp, proto, allocKind);
   1784  }
   1785  if (!shape) {
   1786    return nullptr;
   1787  }
   1788 
   1789  gc::Heap heap = GetInitialHeap(newKind, clasp);
   1790  JSFunction* fun = JSFunction::create(cx, allocKind, heap, shape);
   1791  if (!fun) {
   1792    return nullptr;
   1793  }
   1794 
   1795  if (allocKind == gc::AllocKind::FUNCTION_EXTENDED) {
   1796    flags.setIsExtended();
   1797  }
   1798 
   1799  // Disallow flags that require special union arms to be initialized.
   1800  MOZ_ASSERT(!flags.hasSelfHostedLazyScript());
   1801  MOZ_ASSERT(!flags.isWasmWithJitEntry());
   1802 
   1803  /* Initialize all function members. */
   1804  fun->setArgCount(uint16_t(nargs));
   1805  fun->setFlags(flags);
   1806  if (fun->isInterpreted()) {
   1807    fun->initScript(nullptr);
   1808    fun->initEnvironment(enclosingEnv);
   1809  } else {
   1810    MOZ_ASSERT(fun->isNativeFun());
   1811    fun->initNative(native, nullptr);
   1812  }
   1813  fun->initAtom(atom);
   1814 
   1815 #ifdef DEBUG
   1816  fun->assertFunctionKindIntegrity();
   1817 #endif
   1818 
   1819  return fun;
   1820 }
   1821 
   1822 bool js::GetFunctionPrototype(JSContext* cx, js::GeneratorKind generatorKind,
   1823                              js::FunctionAsyncKind asyncKind,
   1824                              js::MutableHandleObject proto) {
   1825  if (generatorKind == js::GeneratorKind::NotGenerator) {
   1826    if (asyncKind == js::FunctionAsyncKind::SyncFunction) {
   1827      proto.set(nullptr);
   1828      return true;
   1829    }
   1830 
   1831    proto.set(
   1832        GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global()));
   1833  } else {
   1834    if (asyncKind == js::FunctionAsyncKind::SyncFunction) {
   1835      proto.set(GlobalObject::getOrCreateGeneratorFunctionPrototype(
   1836          cx, cx->global()));
   1837    } else {
   1838      proto.set(GlobalObject::getOrCreateAsyncGenerator(cx, cx->global()));
   1839    }
   1840  }
   1841  return !!proto;
   1842 }
   1843 
   1844 #ifdef DEBUG
   1845 static bool CanReuseScriptForClone(JS::Realm* realm, HandleFunction fun,
   1846                                   HandleObject newEnclosingEnv) {
   1847  MOZ_ASSERT(fun->isInterpreted());
   1848 
   1849  if (realm != fun->realm()) {
   1850    return false;
   1851  }
   1852 
   1853  if (newEnclosingEnv->is<GlobalObject>()) {
   1854    return true;
   1855  }
   1856 
   1857  // Don't need to clone the script if newEnclosingEnv is a syntactic scope,
   1858  // since in that case we have some actual scope objects on our scope chain and
   1859  // whatnot; whoever put them there should be responsible for setting our
   1860  // script's flags appropriately.  We hit this case for JSOp::Lambda, for
   1861  // example.
   1862  if (IsSyntacticEnvironment(newEnclosingEnv)) {
   1863    return true;
   1864  }
   1865 
   1866  // We need to clone the script if we're not already marked as having a
   1867  // non-syntactic scope. The HasNonSyntacticScope flag is not computed for lazy
   1868  // scripts so fallback to checking the scope chain.
   1869  BaseScript* script = fun->baseScript();
   1870  return script->hasNonSyntacticScope() ||
   1871         script->enclosingScope()->hasOnChain(ScopeKind::NonSyntactic);
   1872 }
   1873 #endif
   1874 
   1875 static inline JSFunction* NewFunctionClone(JSContext* cx, HandleFunction fun,
   1876                                           HandleObject proto,
   1877                                           gc::Heap heap = gc::Heap::Default,
   1878                                           gc::AllocSite* site = nullptr) {
   1879  MOZ_ASSERT(cx->realm() == fun->realm());
   1880  MOZ_ASSERT(proto);
   1881 
   1882  const JSClass* clasp = fun->getClass();
   1883  gc::AllocKind allocKind = fun->getAllocKind();
   1884  AssertClassMatchesAllocKind(clasp, allocKind);
   1885 
   1886  // If |fun| also has |proto| as prototype (the common case) we can reuse its
   1887  // shape for the clone. This works because |fun| isn't exposed to script.
   1888  Rooted<SharedShape*> shape(cx);
   1889  if (fun->staticPrototype() == proto) {
   1890    shape = fun->sharedShape();
   1891    MOZ_ASSERT(shape->propMapLength() == 0);
   1892    MOZ_ASSERT(shape->objectFlags().isEmpty());
   1893    MOZ_ASSERT(shape->realm() == cx->realm());
   1894  } else {
   1895    shape = GetFunctionShape(cx, clasp, proto, allocKind);
   1896    if (!shape) {
   1897      return nullptr;
   1898    }
   1899  }
   1900 
   1901  JSFunction* clone = JSFunction::create(cx, allocKind, heap, shape, site);
   1902  if (!clone) {
   1903    return nullptr;
   1904  }
   1905 
   1906  // The following flags shouldn't be set or cloned.
   1907  MOZ_ASSERT(!fun->flags().hasResolvedLength());
   1908  MOZ_ASSERT(!fun->flags().hasResolvedName());
   1909 
   1910  clone->setArgCount(fun->nargs());
   1911  clone->setFlags(fun->flags());
   1912 
   1913  // Note: |clone| and |fun| are same-zone so we don't need to call markAtom.
   1914  clone->initAtom(fun->maybePartialDisplayAtom());
   1915 
   1916 #ifdef DEBUG
   1917  clone->assertFunctionKindIntegrity();
   1918 #endif
   1919 
   1920  return clone;
   1921 }
   1922 
   1923 JSFunction* js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun,
   1924                                         HandleObject enclosingEnv,
   1925                                         HandleObject proto, gc::Heap heap,
   1926                                         gc::AllocSite* site) {
   1927  MOZ_ASSERT(cx->realm() == fun->realm());
   1928  MOZ_ASSERT(NewFunctionEnvironmentIsWellFormed(cx, enclosingEnv));
   1929  MOZ_ASSERT(fun->isInterpreted());
   1930  MOZ_ASSERT(fun->hasBaseScript());
   1931  MOZ_ASSERT(CanReuseScriptForClone(cx->realm(), fun, enclosingEnv));
   1932 
   1933  JSFunction* clone = NewFunctionClone(cx, fun, proto, heap, site);
   1934  if (!clone) {
   1935    return nullptr;
   1936  }
   1937 
   1938  BaseScript* base = fun->baseScript();
   1939  clone->initScript(base);
   1940  clone->initEnvironment(enclosingEnv);
   1941 
   1942 #ifdef DEBUG
   1943  // Assert extended slots don't need to be copied.
   1944  if (fun->isExtended()) {
   1945    for (unsigned i = 0; i < FunctionExtended::NUM_EXTENDED_SLOTS; i++) {
   1946      MOZ_ASSERT(fun->getExtendedSlot(i).isUndefined());
   1947      MOZ_ASSERT(clone->getExtendedSlot(i).isUndefined());
   1948    }
   1949  }
   1950 #endif
   1951 
   1952  return clone;
   1953 }
   1954 
   1955 JSFunction* js::CloneAsmJSModuleFunction(JSContext* cx, HandleFunction fun) {
   1956  MOZ_ASSERT(fun->isNativeFun());
   1957  MOZ_ASSERT(IsAsmJSModule(fun));
   1958  MOZ_ASSERT(fun->isExtended());
   1959  MOZ_ASSERT(cx->compartment() == fun->compartment());
   1960 
   1961  RootedObject proto(cx, fun->staticPrototype());
   1962  JSFunction* clone = NewFunctionClone(cx, fun, proto);
   1963  if (!clone) {
   1964    return nullptr;
   1965  }
   1966 
   1967  MOZ_ASSERT(fun->native() == InstantiateAsmJS);
   1968  MOZ_ASSERT(!fun->hasJitInfo());
   1969  clone->initNative(InstantiateAsmJS, nullptr);
   1970 
   1971  JSObject* moduleObj =
   1972      &fun->getExtendedSlot(FunctionExtended::ASMJS_MODULE_SLOT).toObject();
   1973  clone->initExtendedSlot(FunctionExtended::ASMJS_MODULE_SLOT,
   1974                          ObjectValue(*moduleObj));
   1975 
   1976  return clone;
   1977 }
   1978 
   1979 static JSAtom* SymbolToFunctionName(JSContext* cx, JS::Symbol* symbol,
   1980                                    FunctionPrefixKind prefixKind) {
   1981  // Step 4.a.
   1982  JSAtom* desc = symbol->description();
   1983 
   1984  // Step 4.b, no prefix fastpath.
   1985  if (!desc && prefixKind == FunctionPrefixKind::None) {
   1986    return cx->names().empty_;
   1987  }
   1988 
   1989  // Step 5 (reordered).
   1990  StringBuilder sb(cx);
   1991  if (prefixKind == FunctionPrefixKind::Get) {
   1992    if (!sb.append("get ")) {
   1993      return nullptr;
   1994    }
   1995  } else if (prefixKind == FunctionPrefixKind::Set) {
   1996    if (!sb.append("set ")) {
   1997      return nullptr;
   1998    }
   1999  }
   2000 
   2001  // Step 4.b.
   2002  if (desc) {
   2003    // Note: Private symbols are wedged in, as implementation wise they're
   2004    // PrivateNameSymbols with a the source level name as a description
   2005    // i.e. obj.#f desugars to obj.[PrivateNameSymbol("#f")], however
   2006    // they don't use the symbol naming, but rather property naming.
   2007    if (symbol->isPrivateName()) {
   2008      if (!sb.append(desc)) {
   2009        return nullptr;
   2010      }
   2011    } else {
   2012      // Step 4.c.
   2013      if (!sb.append('[') || !sb.append(desc) || !sb.append(']')) {
   2014        return nullptr;
   2015      }
   2016    }
   2017  }
   2018  return sb.finishAtom();
   2019 }
   2020 
   2021 /*
   2022 * Return an atom for use as the name of a builtin method with the given
   2023 * property id.
   2024 *
   2025 * Function names are always strings. If id is the well-known @@iterator
   2026 * symbol, this returns "[Symbol.iterator]".  If a prefix is supplied the final
   2027 * name is |prefix + " " + name|.
   2028 *
   2029 * Implements steps 3-5 of 9.2.11 SetFunctionName in ES2016.
   2030 */
   2031 JSAtom* js::IdToFunctionName(
   2032    JSContext* cx, HandleId id,
   2033    FunctionPrefixKind prefixKind /* = FunctionPrefixKind::None */) {
   2034  MOZ_ASSERT(id.isString() || id.isSymbol() || id.isInt());
   2035 
   2036  // No prefix fastpath.
   2037  if (id.isAtom() && prefixKind == FunctionPrefixKind::None) {
   2038    return id.toAtom();
   2039  }
   2040 
   2041  // Step 3 (implicit).
   2042 
   2043  // Step 4.
   2044  if (id.isSymbol()) {
   2045    return SymbolToFunctionName(cx, id.toSymbol(), prefixKind);
   2046  }
   2047 
   2048  // Step 5.
   2049  RootedValue idv(cx, IdToValue(id));
   2050  return NameToFunctionName(cx, idv, prefixKind);
   2051 }
   2052 
   2053 bool js::SetFunctionName(JSContext* cx, HandleFunction fun, HandleValue name,
   2054                         FunctionPrefixKind prefixKind) {
   2055  MOZ_ASSERT(name.isString() || name.isSymbol() || name.isNumeric());
   2056 
   2057  // `fun` is a newly created function, so it can't already have an inferred
   2058  // name.
   2059  MOZ_ASSERT(!fun->hasInferredName());
   2060 
   2061  // Anonymous functions should neither have an own 'name' property nor a
   2062  // resolved name at this point.
   2063  MOZ_ASSERT(!fun->containsPure(cx->names().name));
   2064  MOZ_ASSERT(!fun->hasResolvedName());
   2065 
   2066  JSAtom* funName = name.isSymbol()
   2067                        ? SymbolToFunctionName(cx, name.toSymbol(), prefixKind)
   2068                        : NameToFunctionName(cx, name, prefixKind);
   2069  if (!funName) {
   2070    return false;
   2071  }
   2072 
   2073  fun->setInferredName(funName);
   2074 
   2075  return true;
   2076 }
   2077 
   2078 JSFunction* js::DefineFunction(
   2079    JSContext* cx, HandleObject obj, HandleId id, Native native, unsigned nargs,
   2080    unsigned flags, gc::AllocKind allocKind /* = AllocKind::FUNCTION */) {
   2081  Rooted<JSAtom*> atom(cx, IdToFunctionName(cx, id));
   2082  if (!atom) {
   2083    return nullptr;
   2084  }
   2085 
   2086  MOZ_ASSERT(native);
   2087 
   2088  RootedFunction fun(cx);
   2089  if (flags & JSFUN_CONSTRUCTOR) {
   2090    fun = NewNativeConstructor(cx, native, nargs, atom, allocKind);
   2091  } else {
   2092    fun = NewNativeFunction(cx, native, nargs, atom, allocKind);
   2093  }
   2094 
   2095  if (!fun) {
   2096    return nullptr;
   2097  }
   2098 
   2099  RootedValue funVal(cx, ObjectValue(*fun));
   2100  if (!DefineDataProperty(cx, obj, id, funVal, flags & ~JSFUN_FLAGS_MASK)) {
   2101    return nullptr;
   2102  }
   2103 
   2104  return fun;
   2105 }
   2106 
   2107 void js::ReportIncompatibleMethod(JSContext* cx, const CallArgs& args,
   2108                                  const JSClass* clasp) {
   2109  HandleValue thisv = args.thisv();
   2110 
   2111 #ifdef DEBUG
   2112  switch (thisv.type()) {
   2113    case ValueType::Object:
   2114      MOZ_ASSERT(thisv.toObject().getClass() != clasp ||
   2115                 !thisv.toObject().is<NativeObject>() ||
   2116                 !thisv.toObject().staticPrototype() ||
   2117                 thisv.toObject().staticPrototype()->getClass() != clasp);
   2118      break;
   2119    case ValueType::String:
   2120      MOZ_ASSERT(clasp != &StringObject::class_);
   2121      break;
   2122    case ValueType::Double:
   2123    case ValueType::Int32:
   2124      MOZ_ASSERT(clasp != &NumberObject::class_);
   2125      break;
   2126    case ValueType::Boolean:
   2127      MOZ_ASSERT(clasp != &BooleanObject::class_);
   2128      break;
   2129    case ValueType::Symbol:
   2130      MOZ_ASSERT(clasp != &SymbolObject::class_);
   2131      break;
   2132    case ValueType::BigInt:
   2133      MOZ_ASSERT(clasp != &BigIntObject::class_);
   2134      break;
   2135    case ValueType::Undefined:
   2136    case ValueType::Null:
   2137      break;
   2138    case ValueType::Magic:
   2139    case ValueType::PrivateGCThing:
   2140      MOZ_CRASH("unexpected type");
   2141  }
   2142 #endif
   2143 
   2144  if (JSFunction* fun = ReportIfNotFunction(cx, args.calleev())) {
   2145    UniqueChars funNameBytes;
   2146    if (const char* funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
   2147      JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
   2148                               JSMSG_INCOMPATIBLE_PROTO, clasp->name, funName,
   2149                               InformalValueTypeName(thisv));
   2150    }
   2151  }
   2152 }
   2153 
   2154 void js::ReportIncompatible(JSContext* cx, const CallArgs& args) {
   2155  if (JSFunction* fun = ReportIfNotFunction(cx, args.calleev())) {
   2156    UniqueChars funNameBytes;
   2157    if (const char* funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
   2158      JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
   2159                               JSMSG_INCOMPATIBLE_METHOD, funName, "method",
   2160                               InformalValueTypeName(args.thisv()));
   2161    }
   2162  }
   2163 }
   2164 
   2165 namespace JS {
   2166 namespace detail {
   2167 
   2168 JS_PUBLIC_API void CheckIsValidConstructible(const Value& calleev) {
   2169  MOZ_ASSERT(calleev.toObject().isConstructor());
   2170 }
   2171 
   2172 }  // namespace detail
   2173 }  // namespace JS