LCOV - code coverage report
Current view: top level - js/src/vm - GlobalObject.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 272 374 72.7 %
Date: 2017-07-14 16:53:18 Functions: 27 36 75.0 %
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             : #include "vm/GlobalObject.h"
       8             : 
       9             : #include "jscntxt.h"
      10             : #include "jsdate.h"
      11             : #include "jsexn.h"
      12             : #include "jsfriendapi.h"
      13             : #include "jsmath.h"
      14             : #include "json.h"
      15             : #include "jsprototypes.h"
      16             : #include "jsweakmap.h"
      17             : 
      18             : #include "builtin/AtomicsObject.h"
      19             : #include "builtin/DataViewObject.h"
      20             : #include "builtin/Eval.h"
      21             : #if EXPOSE_INTL_API
      22             : # include "builtin/Intl.h"
      23             : #endif
      24             : #include "builtin/MapObject.h"
      25             : #include "builtin/ModuleObject.h"
      26             : #include "builtin/Object.h"
      27             : #include "builtin/Promise.h"
      28             : #include "builtin/RegExp.h"
      29             : #include "builtin/SelfHostingDefines.h"
      30             : #include "builtin/SymbolObject.h"
      31             : #include "builtin/TypedObject.h"
      32             : #include "builtin/WeakMapObject.h"
      33             : #include "builtin/WeakSetObject.h"
      34             : #include "vm/Debugger.h"
      35             : #include "vm/EnvironmentObject.h"
      36             : #include "vm/HelperThreads.h"
      37             : #include "vm/PIC.h"
      38             : #include "vm/RegExpStatics.h"
      39             : #include "vm/RegExpStaticsObject.h"
      40             : #include "vm/StopIterationObject.h"
      41             : #include "wasm/WasmJS.h"
      42             : 
      43             : #include "jscompartmentinlines.h"
      44             : #include "jsobjinlines.h"
      45             : #include "jsscriptinlines.h"
      46             : 
      47             : #include "vm/NativeObject-inl.h"
      48             : 
      49             : using namespace js;
      50             : 
      51             : struct ProtoTableEntry {
      52             :     const Class* clasp;
      53             :     ClassInitializerOp init;
      54             : };
      55             : 
      56             : namespace js {
      57             : 
      58             : #define DECLARE_PROTOTYPE_CLASS_INIT(name,code,init,clasp) \
      59             :     extern JSObject* init(JSContext* cx, Handle<JSObject*> obj);
      60             : JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT)
      61             : #undef DECLARE_PROTOTYPE_CLASS_INIT
      62             : 
      63             : } // namespace js
      64             : 
      65             : JSObject*
      66           0 : js::InitViaClassSpec(JSContext* cx, Handle<JSObject*> obj)
      67             : {
      68           0 :     MOZ_CRASH("InitViaClassSpec() should not be called.");
      69             : }
      70             : 
      71             : static const ProtoTableEntry protoTable[JSProto_LIMIT] = {
      72             : #define INIT_FUNC(name,code,init,clasp) { clasp, init },
      73             : #define INIT_FUNC_DUMMY(name,code,init,clasp) { nullptr, nullptr },
      74             :     JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY)
      75             : #undef INIT_FUNC_DUMMY
      76             : #undef INIT_FUNC
      77           3 : };
      78             : 
      79             : JS_FRIEND_API(const js::Class*)
      80        2166 : js::ProtoKeyToClass(JSProtoKey key)
      81             : {
      82        2166 :     MOZ_ASSERT(key < JSProto_LIMIT);
      83        2166 :     return protoTable[key].clasp;
      84             : }
      85             : 
      86             : // This method is not in the header file to avoid having to include
      87             : // TypedObject.h from GlobalObject.h. It is not generally perf
      88             : // sensitive.
      89             : TypedObjectModuleObject&
      90           0 : js::GlobalObject::getTypedObjectModule() const {
      91           0 :     Value v = getConstructor(JSProto_TypedObject);
      92             :     // only gets called from contexts where TypedObject must be initialized
      93           0 :     MOZ_ASSERT(v.isObject());
      94           0 :     return v.toObject().as<TypedObjectModuleObject>();
      95             : }
      96             : 
      97             : /* static */ bool
      98        1970 : GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key)
      99             : {
     100        1970 :     if (key == JSProto_WebAssembly)
     101           6 :         return !wasm::HasSupport(cx);
     102             : 
     103             : #ifdef ENABLE_SHARED_ARRAY_BUFFER
     104             :     // Return true if the given constructor has been disabled at run-time.
     105        1964 :     switch (key) {
     106             :       case JSProto_Atomics:
     107             :       case JSProto_SharedArrayBuffer:
     108          12 :         return !cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled();
     109             :       default:
     110        1952 :         return false;
     111             :     }
     112             : #else
     113             :     return false;
     114             : #endif
     115             : }
     116             : 
     117             : /* static */ bool
     118        4695 : GlobalObject::ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
     119             : {
     120        4695 :     if (global->isStandardClassResolved(key))
     121        3362 :         return true;
     122        1333 :     return resolveConstructor(cx, global, key);
     123             : }
     124             : 
     125             : /* static*/ bool
     126        1709 : GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
     127             : {
     128        1709 :     MOZ_ASSERT(!global->isStandardClassResolved(key));
     129             : 
     130             :     // Prohibit collection of allocation metadata. Metadata builders shouldn't
     131             :     // need to observe lazily-constructed prototype objects coming into
     132             :     // existence. And assertions start to fail when the builder itself attempts
     133             :     // an allocation that re-entrantly tries to create the same prototype.
     134        3419 :     AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
     135             : 
     136             :     // Constructor resolution may execute self-hosted scripts. These
     137             :     // self-hosted scripts do not call out to user code by construction. Allow
     138             :     // all scripts to execute, even in debuggee compartments that are paused.
     139        3419 :     AutoSuppressDebuggeeNoExecuteChecks suppressNX(cx);
     140             : 
     141             :     // There are two different kinds of initialization hooks. One of them is
     142             :     // the class js::InitFoo hook, defined in a JSProtoKey-keyed table at the
     143             :     // top of this file. The other lives in the ClassSpec for classes that
     144             :     // define it. Classes may use one or the other, but not both.
     145        1709 :     ClassInitializerOp init = protoTable[key].init;
     146        1709 :     if (init == InitViaClassSpec)
     147        1418 :         init = nullptr;
     148             : 
     149        1709 :     const Class* clasp = ProtoKeyToClass(key);
     150        1709 :     if (!init && !clasp)
     151          30 :         return true;  // JSProto_Null or a compile-time-disabled feature.
     152             : 
     153        1679 :     if (skipDeselectedConstructor(cx, key))
     154           0 :         return true;
     155             : 
     156             :     // Some classes have no init routine, which means that they're disabled at
     157             :     // compile-time. We could try to enforce that callers never pass such keys
     158             :     // to resolveConstructor, but that would cramp the style of consumers like
     159             :     // GlobalObject::initStandardClasses that want to just carpet-bomb-call
     160             :     // ensureConstructor with every JSProtoKey. So it's easier to just handle
     161             :     // it here.
     162        1679 :     bool haveSpec = clasp && clasp->specDefined();
     163        1679 :     if (!init && !haveSpec)
     164           0 :         return true;
     165             : 
     166             :     // See if there's an old-style initialization hook.
     167        1679 :     if (init) {
     168         261 :         MOZ_ASSERT(!haveSpec);
     169         261 :         return init(cx, global);
     170             :     }
     171             : 
     172             :     //
     173             :     // Ok, we're doing it with a class spec.
     174             :     //
     175             : 
     176        1418 :     bool isObjectOrFunction = key == JSProto_Function || key == JSProto_Object;
     177             : 
     178             :     // We need to create the prototype first, and immediately stash it in the
     179             :     // slot. This is so the following bootstrap ordering is possible:
     180             :     // * Object.prototype
     181             :     // * Function.prototype
     182             :     // * Function
     183             :     // * Object
     184             :     //
     185             :     // We get the above when Object is resolved before Function. If Function
     186             :     // is resolved before Object, we'll end up re-entering resolveConstructor
     187             :     // for Function, which is a problem. So if Function is being resolved
     188             :     // before Object.prototype exists, we just resolve Object instead, since we
     189             :     // know that Function will also be resolved before we return.
     190        1418 :     if (key == JSProto_Function && global->getPrototype(JSProto_Object).isUndefined())
     191          16 :         return resolveConstructor(cx, global, JSProto_Object);
     192             : 
     193             :     // We don't always have a prototype (i.e. Math and JSON). If we don't,
     194             :     // |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
     195             :     // should all be null.
     196        2805 :     RootedObject proto(cx);
     197        1402 :     if (ClassObjectCreationOp createPrototype = clasp->specCreatePrototypeHook()) {
     198        1402 :         proto = createPrototype(cx, key);
     199        1402 :         if (!proto)
     200           0 :             return false;
     201             : 
     202        1402 :         if (isObjectOrFunction) {
     203             :             // Make sure that creating the prototype didn't recursively resolve
     204             :             // our own constructor. We can't just assert that there's no
     205             :             // prototype; OOMs can result in incomplete resolutions in which
     206             :             // the prototype is saved but not the constructor. So use the same
     207             :             // criteria that protects entry into this function.
     208         622 :             MOZ_ASSERT(!global->isStandardClassResolved(key));
     209             : 
     210         622 :             global->setPrototype(key, ObjectValue(*proto));
     211             :         }
     212             :     }
     213             : 
     214             :     // Create the constructor.
     215        2805 :     RootedObject ctor(cx, clasp->specCreateConstructorHook()(cx, key));
     216        1402 :     if (!ctor)
     217           0 :         return false;
     218             : 
     219        2805 :     RootedId id(cx, NameToId(ClassName(key, cx)));
     220        1402 :     if (isObjectOrFunction) {
     221         622 :         if (clasp->specShouldDefineConstructor()) {
     222        1244 :             RootedValue ctorValue(cx, ObjectValue(*ctor));
     223         622 :             if (!DefineProperty(cx, global, id, ctorValue, nullptr, nullptr, JSPROP_RESOLVING))
     224           0 :                 return false;
     225             :         }
     226             : 
     227         622 :         global->setConstructor(key, ObjectValue(*ctor));
     228             :     }
     229             : 
     230             :     // If we're operating on the self-hosting global, we don't want any
     231             :     // functions and properties on the builtins and their prototypes.
     232        1402 :     if (!cx->runtime()->isSelfHostingGlobal(global)) {
     233        1396 :         if (const JSFunctionSpec* funs = clasp->specPrototypeFunctions()) {
     234        1274 :             if (!JS_DefineFunctions(cx, proto, funs))
     235           0 :                 return false;
     236             :         }
     237        1396 :         if (const JSPropertySpec* props = clasp->specPrototypeProperties()) {
     238        1083 :             if (!JS_DefineProperties(cx, proto, props))
     239           0 :                 return false;
     240             :         }
     241        1396 :         if (const JSFunctionSpec* funs = clasp->specConstructorFunctions()) {
     242         747 :             if (!JS_DefineFunctions(cx, ctor, funs))
     243           0 :                 return false;
     244             :         }
     245        1397 :         if (const JSPropertySpec* props = clasp->specConstructorProperties()) {
     246         605 :             if (!JS_DefineProperties(cx, ctor, props))
     247           0 :                 return false;
     248             :         }
     249             :     }
     250             : 
     251             :     // If the prototype exists, link it with the constructor.
     252        1403 :     if (proto && !LinkConstructorAndPrototype(cx, ctor, proto))
     253           0 :         return false;
     254             : 
     255             :     // Call the post-initialization hook, if provided.
     256        1403 :     if (FinishClassInitOp finishInit = clasp->specFinishInitHook()) {
     257         687 :         if (!finishInit(cx, ctor, proto))
     258           0 :             return false;
     259             :     }
     260             : 
     261        1403 :     if (!isObjectOrFunction) {
     262             :         // Any operations that modifies the global object should be placed
     263             :         // after any other fallible operations.
     264             : 
     265             :         // Fallible operation that modifies the global object.
     266         781 :         if (clasp->specShouldDefineConstructor()) {
     267        1378 :             RootedValue ctorValue(cx, ObjectValue(*ctor));
     268         689 :             if (!DefineProperty(cx, global, id, ctorValue, nullptr, nullptr, JSPROP_RESOLVING))
     269           0 :                 return false;
     270             :         }
     271             : 
     272             :         // Infallible operations that modify the global object.
     273         781 :         global->setConstructor(key, ObjectValue(*ctor));
     274         781 :         if (proto)
     275         781 :             global->setPrototype(key, ObjectValue(*proto));
     276             :     }
     277             : 
     278        1403 :     return true;
     279             : }
     280             : 
     281             : /* static */ bool
     282         194 : GlobalObject::initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
     283             :                                      JSProtoKey key, HandleObject ctor, HandleObject proto)
     284             : {
     285         194 :     MOZ_ASSERT(!global->empty()); // reserved slots already allocated
     286         194 :     MOZ_ASSERT(key != JSProto_Null);
     287         194 :     MOZ_ASSERT(ctor);
     288         194 :     MOZ_ASSERT(proto);
     289             : 
     290         388 :     RootedId id(cx, NameToId(ClassName(key, cx)));
     291         194 :     MOZ_ASSERT(!global->lookup(cx, id));
     292             : 
     293         388 :     RootedValue ctorValue(cx, ObjectValue(*ctor));
     294         194 :     if (!DefineProperty(cx, global, id, ctorValue, nullptr, nullptr, JSPROP_RESOLVING))
     295           0 :         return false;
     296             : 
     297         194 :     global->setConstructor(key, ObjectValue(*ctor));
     298         194 :     global->setPrototype(key, ObjectValue(*proto));
     299         194 :     return true;
     300             : }
     301             : 
     302             : GlobalObject*
     303         311 : GlobalObject::createInternal(JSContext* cx, const Class* clasp)
     304             : {
     305         311 :     MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
     306         311 :     MOZ_ASSERT(clasp->isTrace(JS_GlobalObjectTraceHook));
     307             : 
     308         311 :     JSObject* obj = NewObjectWithGivenProto(cx, clasp, nullptr, SingletonObject);
     309         311 :     if (!obj)
     310           0 :         return nullptr;
     311             : 
     312         622 :     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     313         311 :     MOZ_ASSERT(global->isUnqualifiedVarObj());
     314             : 
     315             :     // Initialize the private slot to null if present, as GC can call class
     316             :     // hooks before the caller gets to set this to a non-garbage value.
     317         311 :     if (clasp->flags & JSCLASS_HAS_PRIVATE)
     318         284 :         global->setPrivate(nullptr);
     319             : 
     320             :     Rooted<LexicalEnvironmentObject*> lexical(cx,
     321         622 :         LexicalEnvironmentObject::createGlobal(cx, global));
     322         311 :     if (!lexical)
     323           0 :         return nullptr;
     324         311 :     global->setReservedSlot(LEXICAL_ENVIRONMENT, ObjectValue(*lexical));
     325             : 
     326         622 :     Rooted<GlobalScope*> emptyGlobalScope(cx, GlobalScope::createEmpty(cx, ScopeKind::Global));
     327         311 :     if (!emptyGlobalScope)
     328           0 :         return nullptr;
     329         311 :     global->setReservedSlot(EMPTY_GLOBAL_SCOPE, PrivateGCThingValue(emptyGlobalScope));
     330             : 
     331         311 :     cx->compartment()->initGlobal(*global);
     332             : 
     333         311 :     if (!JSObject::setQualifiedVarObj(cx, global))
     334           0 :         return nullptr;
     335         311 :     if (!JSObject::setDelegate(cx, global))
     336           0 :         return nullptr;
     337             : 
     338         311 :     return global;
     339             : }
     340             : 
     341             : /* static */ GlobalObject*
     342         308 : GlobalObject::new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
     343             :                    JS::OnNewGlobalHookOption hookOption,
     344             :                    const JS::CompartmentOptions& options)
     345             : {
     346         308 :     MOZ_ASSERT(!cx->isExceptionPending());
     347         308 :     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     348             : 
     349         308 :     JSCompartment* compartment = NewCompartment(cx, principals, options);
     350         308 :     if (!compartment)
     351           0 :         return nullptr;
     352             : 
     353         616 :     Rooted<GlobalObject*> global(cx);
     354             :     {
     355         616 :         AutoCompartmentUnchecked ac(cx, compartment);
     356         308 :         global = GlobalObject::createInternal(cx, clasp);
     357         308 :         if (!global)
     358           0 :             return nullptr;
     359             : 
     360         308 :         if (hookOption == JS::FireOnNewGlobalHook)
     361          16 :             JS_FireOnNewGlobalObject(cx, global);
     362             :     }
     363             : 
     364         308 :     return global;
     365             : }
     366             : 
     367             : LexicalEnvironmentObject&
     368       53013 : GlobalObject::lexicalEnvironment() const
     369             : {
     370       53013 :     return getReservedSlot(LEXICAL_ENVIRONMENT).toObject().as<LexicalEnvironmentObject>();
     371             : }
     372             : 
     373             : GlobalScope&
     374        4879 : GlobalObject::emptyGlobalScope() const
     375             : {
     376        4879 :     const Value& v = getReservedSlot(EMPTY_GLOBAL_SCOPE);
     377        4879 :     MOZ_ASSERT(v.isPrivateGCThing() && v.traceKind() == JS::TraceKind::Scope);
     378        4879 :     return static_cast<Scope*>(v.toGCThing())->as<GlobalScope>();
     379             : }
     380             : 
     381             : /* static */ bool
     382           0 : GlobalObject::getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
     383             :                               MutableHandleObject eval)
     384             : {
     385           0 :     if (!getOrCreateObjectPrototype(cx, global))
     386           0 :         return false;
     387           0 :     eval.set(&global->getSlot(EVAL).toObject());
     388           0 :     return true;
     389             : }
     390             : 
     391             : bool
     392           2 : GlobalObject::valueIsEval(const Value& val)
     393             : {
     394           2 :     Value eval = getSlot(EVAL);
     395           2 :     return eval.isObject() && eval == val;
     396             : }
     397             : 
     398             : /* static */ bool
     399           6 : GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global)
     400             : {
     401             :     /* Define a top-level property 'undefined' with the undefined value. */
     402           6 :     if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
     403             :                         nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
     404             :     {
     405           0 :         return false;
     406             :     }
     407             : 
     408         342 :     for (size_t k = 0; k < JSProto_LIMIT; ++k) {
     409         336 :         if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
     410           0 :             return false;
     411             :     }
     412           6 :     return true;
     413             : }
     414             : 
     415             : /**
     416             :  * Initializes a builtin constructor and its prototype without defining any
     417             :  * properties or functions on it.
     418             :  *
     419             :  * Used in self-hosting to install the few builtin constructors required by
     420             :  * self-hosted builtins.
     421             :  */
     422             : static bool
     423          12 : InitBareBuiltinCtor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey protoKey)
     424             : {
     425          12 :     MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(global));
     426          12 :     const Class* clasp = ProtoKeyToClass(protoKey);
     427          24 :     RootedObject proto(cx);
     428          12 :     proto = clasp->specCreatePrototypeHook()(cx, protoKey);
     429          12 :     if (!proto)
     430           0 :         return false;
     431             : 
     432          24 :     RootedObject ctor(cx, clasp->specCreateConstructorHook()(cx, protoKey));
     433          12 :     if (!ctor)
     434           0 :         return false;
     435             : 
     436          12 :     return GlobalObject::initBuiltinConstructor(cx, global, protoKey, ctor, proto);
     437             : }
     438             : 
     439             : /**
     440             :  * The self-hosting global only gets a small subset of all standard classes.
     441             :  * Even those are only created as bare constructors without any properties
     442             :  * or functions.
     443             :  */
     444             : /* static */ bool
     445           3 : GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> global,
     446             :                                       const JSFunctionSpec* builtins)
     447             : {
     448             :     // Define a top-level property 'undefined' with the undefined value.
     449           3 :     if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
     450             :                         nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
     451             :     {
     452           0 :         return false;
     453             :     }
     454             : 
     455           6 :     RootedValue std_isConcatSpreadable(cx);
     456           3 :     std_isConcatSpreadable.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::isConcatSpreadable));
     457           3 :     if (!JS_DefineProperty(cx, global, "std_isConcatSpreadable", std_isConcatSpreadable,
     458             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     459             :     {
     460           0 :         return false;
     461             :     }
     462             : 
     463             :     // Define a top-level property 'std_iterator' with the name of the method
     464             :     // used by for-of loops to create an iterator.
     465           6 :     RootedValue std_iterator(cx);
     466           3 :     std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator));
     467           3 :     if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator,
     468             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     469             :     {
     470           0 :         return false;
     471             :     }
     472             : 
     473           6 :     RootedValue std_match(cx);
     474           3 :     std_match.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::match));
     475           3 :     if (!JS_DefineProperty(cx, global, "std_match", std_match,
     476             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     477             :     {
     478           0 :         return false;
     479             :     }
     480             : 
     481           6 :     RootedValue std_replace(cx);
     482           3 :     std_replace.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::replace));
     483           3 :     if (!JS_DefineProperty(cx, global, "std_replace", std_replace,
     484             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     485             :     {
     486           0 :         return false;
     487             :     }
     488             : 
     489           6 :     RootedValue std_search(cx);
     490           3 :     std_search.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::search));
     491           3 :     if (!JS_DefineProperty(cx, global, "std_search", std_search,
     492             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     493             :     {
     494           0 :         return false;
     495             :     }
     496             : 
     497           6 :     RootedValue std_species(cx);
     498           3 :     std_species.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::species));
     499           3 :     if (!JS_DefineProperty(cx, global, "std_species", std_species,
     500             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     501             :     {
     502           0 :         return false;
     503             :     }
     504             : 
     505           6 :     RootedValue std_split(cx);
     506           3 :     std_split.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::split));
     507           3 :     if (!JS_DefineProperty(cx, global, "std_split", std_split,
     508             :                            JSPROP_PERMANENT | JSPROP_READONLY))
     509             :     {
     510           0 :         return false;
     511             :     }
     512             : 
     513           6 :     return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
     514           6 :            InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
     515           6 :            InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
     516           9 :            InitBareBuiltinCtor(cx, global, JSProto_Int32Array) &&
     517          18 :            InitBareSymbolCtor(cx, global) &&
     518          15 :            InitBareWeakMapCtor(cx, global) &&
     519          21 :            InitStopIterationClass(cx, global) &&
     520           9 :            DefineFunctions(cx, global, builtins, AsIntrinsic);
     521             : }
     522             : 
     523             : /* static */ bool
     524           6 : GlobalObject::isRuntimeCodeGenEnabled(JSContext* cx, Handle<GlobalObject*> global)
     525             : {
     526           6 :     HeapSlot& v = global->getSlotRef(RUNTIME_CODEGEN_ENABLED);
     527           6 :     if (v.isUndefined()) {
     528             :         /*
     529             :          * If there are callbacks, make sure that the CSP callback is installed
     530             :          * and that it permits runtime code generation, then cache the result.
     531             :          */
     532           2 :         JSCSPEvalChecker allows = cx->runtime()->securityCallbacks->contentSecurityPolicyAllows;
     533           2 :         Value boolValue = BooleanValue(!allows || allows(cx));
     534           2 :         v.set(global, HeapSlot::Slot, RUNTIME_CODEGEN_ENABLED, boolValue);
     535             :     }
     536           6 :     return !v.isFalse();
     537             : }
     538             : 
     539             : /* static */ bool
     540           0 : GlobalObject::warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag,
     541             :                             unsigned errorNumber)
     542             : {
     543           0 :     Rooted<GlobalObject*> global(cx, &obj->global());
     544           0 :     HeapSlot& v = global->getSlotRef(WARNED_ONCE_FLAGS);
     545           0 :     MOZ_ASSERT_IF(!v.isUndefined(), v.toInt32());
     546           0 :     int32_t flags = v.isUndefined() ? 0 : v.toInt32();
     547           0 :     if (!(flags & flag)) {
     548           0 :         if (!JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
     549             :                                                errorNumber))
     550             :         {
     551           0 :             return false;
     552             :         }
     553           0 :         if (v.isUndefined())
     554           0 :             v.init(global, HeapSlot::Slot, WARNED_ONCE_FLAGS, Int32Value(flags | flag));
     555             :         else
     556           0 :             v.set(global, HeapSlot::Slot, WARNED_ONCE_FLAGS, Int32Value(flags | flag));
     557             :     }
     558           0 :     return true;
     559             : }
     560             : 
     561             : /* static */ JSFunction*
     562         869 : GlobalObject::createConstructor(JSContext* cx, Native ctor, JSAtom* nameArg, unsigned length,
     563             :                                 gc::AllocKind kind, const JSJitInfo* jitInfo)
     564             : {
     565        1738 :     RootedAtom name(cx, nameArg);
     566         869 :     JSFunction* fun = NewNativeConstructor(cx, ctor, length, name, kind);
     567         869 :     if (!fun)
     568           0 :         return nullptr;
     569             : 
     570         869 :     if (jitInfo)
     571         346 :         fun->setJitInfo(jitInfo);
     572             : 
     573         869 :     return fun;
     574             : }
     575             : 
     576             : static NativeObject*
     577         979 : CreateBlankProto(JSContext* cx, const Class* clasp, HandleObject proto, HandleObject global)
     578             : {
     579         979 :     MOZ_ASSERT(clasp != &JSFunction::class_);
     580             : 
     581        1958 :     RootedNativeObject blankProto(cx, NewNativeObjectWithGivenProto(cx, clasp, proto,
     582        1958 :                                                                     SingletonObject));
     583         979 :     if (!blankProto || !JSObject::setDelegate(cx, blankProto))
     584           0 :         return nullptr;
     585             : 
     586         979 :     return blankProto;
     587             : }
     588             : 
     589             : /* static */ NativeObject*
     590         600 : GlobalObject::createBlankPrototype(JSContext* cx, Handle<GlobalObject*> global, const Class* clasp)
     591             : {
     592        1200 :     RootedObject objectProto(cx, getOrCreateObjectPrototype(cx, global));
     593         600 :     if (!objectProto)
     594           0 :         return nullptr;
     595             : 
     596         600 :     return CreateBlankProto(cx, clasp, objectProto, global);
     597             : }
     598             : 
     599             : /* static */ NativeObject*
     600         379 : GlobalObject::createBlankPrototypeInheriting(JSContext* cx, Handle<GlobalObject*> global,
     601             :                                              const Class* clasp, HandleObject proto)
     602             : {
     603         379 :     return CreateBlankProto(cx, clasp, proto, global);
     604             : }
     605             : 
     606             : bool
     607        2342 : js::LinkConstructorAndPrototype(JSContext* cx, JSObject* ctor_, JSObject* proto_,
     608             :                                 unsigned prototypeAttrs, unsigned constructorAttrs)
     609             : {
     610        4684 :     RootedObject ctor(cx, ctor_), proto(cx, proto_);
     611             : 
     612        4684 :     RootedValue protoVal(cx, ObjectValue(*proto));
     613        4684 :     RootedValue ctorVal(cx, ObjectValue(*ctor));
     614             : 
     615       11710 :     return DefineProperty(cx, ctor, cx->names().prototype, protoVal, nullptr, nullptr,
     616       16394 :                           prototypeAttrs) &&
     617        9368 :            DefineProperty(cx, proto, cx->names().constructor, ctorVal, nullptr, nullptr,
     618        4684 :                           constructorAttrs);
     619             : }
     620             : 
     621             : bool
     622         646 : js::DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
     623             :                                  const JSPropertySpec* ps, const JSFunctionSpec* fs)
     624             : {
     625         646 :     if (ps && !JS_DefineProperties(cx, obj, ps))
     626           0 :         return false;
     627         646 :     if (fs && !JS_DefineFunctions(cx, obj, fs))
     628           0 :         return false;
     629         646 :     return true;
     630             : }
     631             : 
     632             : bool
     633         504 : js::DefineToStringTag(JSContext* cx, HandleObject obj, JSAtom* tag)
     634             : {
     635        1008 :     RootedId toStringTagId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().toStringTag));
     636        1008 :     RootedValue tagString(cx, StringValue(tag));
     637        1008 :     return DefineProperty(cx, obj, toStringTagId, tagString, nullptr, nullptr, JSPROP_READONLY);
     638             : }
     639             : 
     640             : static void
     641           0 : GlobalDebuggees_finalize(FreeOp* fop, JSObject* obj)
     642             : {
     643           0 :     MOZ_ASSERT(fop->maybeOnHelperThread());
     644           0 :     fop->delete_((GlobalObject::DebuggerVector*) obj->as<NativeObject>().getPrivate());
     645           0 : }
     646             : 
     647             : static const ClassOps
     648             : GlobalDebuggees_classOps = {
     649             :     nullptr,
     650             :     nullptr,
     651             :     nullptr,
     652             :     nullptr,
     653             :     nullptr,
     654             :     nullptr,
     655             :     nullptr,
     656             :     nullptr,
     657             :     GlobalDebuggees_finalize
     658             : };
     659             : 
     660             : static const Class
     661             : GlobalDebuggees_class = {
     662             :     "GlobalDebuggee",
     663             :     JSCLASS_HAS_PRIVATE |
     664             :     JSCLASS_BACKGROUND_FINALIZE,
     665             :     &GlobalDebuggees_classOps
     666             : };
     667             : 
     668             : GlobalObject::DebuggerVector*
     669       13051 : GlobalObject::getDebuggers() const
     670             : {
     671       13051 :     Value debuggers = getReservedSlot(DEBUGGERS);
     672       13051 :     if (debuggers.isUndefined())
     673       13051 :         return nullptr;
     674           0 :     MOZ_ASSERT(debuggers.toObject().getClass() == &GlobalDebuggees_class);
     675           0 :     return (DebuggerVector*) debuggers.toObject().as<NativeObject>().getPrivate();
     676             : }
     677             : 
     678             : /* static */ GlobalObject::DebuggerVector*
     679           0 : GlobalObject::getOrCreateDebuggers(JSContext* cx, Handle<GlobalObject*> global)
     680             : {
     681           0 :     assertSameCompartment(cx, global);
     682           0 :     DebuggerVector* debuggers = global->getDebuggers();
     683           0 :     if (debuggers)
     684           0 :         return debuggers;
     685             : 
     686           0 :     NativeObject* obj = NewNativeObjectWithGivenProto(cx, &GlobalDebuggees_class, nullptr);
     687           0 :     if (!obj)
     688           0 :         return nullptr;
     689           0 :     debuggers = cx->new_<DebuggerVector>();
     690           0 :     if (!debuggers)
     691           0 :         return nullptr;
     692           0 :     obj->setPrivate(debuggers);
     693           0 :     global->setReservedSlot(DEBUGGERS, ObjectValue(*obj));
     694           0 :     return debuggers;
     695             : }
     696             : 
     697             : /* static */ NativeObject*
     698          18 : GlobalObject::getOrCreateForOfPICObject(JSContext* cx, Handle<GlobalObject*> global)
     699             : {
     700          18 :     assertSameCompartment(cx, global);
     701          18 :     NativeObject* forOfPIC = global->getForOfPICObject();
     702          18 :     if (forOfPIC)
     703           0 :         return forOfPIC;
     704             : 
     705          18 :     forOfPIC = ForOfPIC::createForOfPICObject(cx, global);
     706          18 :     if (!forOfPIC)
     707           0 :         return nullptr;
     708          18 :     global->setReservedSlot(FOR_OF_PIC_CHAIN, ObjectValue(*forOfPIC));
     709          18 :     return forOfPIC;
     710             : }
     711             : 
     712             : bool
     713           0 : GlobalObject::hasRegExpStatics() const
     714             : {
     715           0 :     return !getSlot(REGEXP_STATICS).isUndefined();
     716             : }
     717             : 
     718             : /* static */ RegExpStatics*
     719         264 : GlobalObject::getRegExpStatics(JSContext* cx, Handle<GlobalObject*> global)
     720             : {
     721         264 :     MOZ_ASSERT(cx);
     722         264 :     RegExpStaticsObject* resObj = nullptr;
     723         264 :     const Value& val = global->getSlot(REGEXP_STATICS);
     724         264 :     if (!val.isObject()) {
     725          13 :         MOZ_ASSERT(val.isUndefined());
     726          13 :         resObj = RegExpStatics::create(cx, global);
     727          13 :         if (!resObj)
     728           0 :             return nullptr;
     729             : 
     730          13 :         global->initSlot(REGEXP_STATICS, ObjectValue(*resObj));
     731             :     } else {
     732         251 :         resObj = &val.toObject().as<RegExpStaticsObject>();
     733             :     }
     734         264 :     return static_cast<RegExpStatics*>(resObj->getPrivate(/* nfixed = */ 1));
     735             : }
     736             : 
     737             : RegExpStatics*
     738           0 : GlobalObject::getAlreadyCreatedRegExpStatics() const
     739             : {
     740           0 :     const Value& val = this->getSlot(REGEXP_STATICS);
     741           0 :     MOZ_ASSERT(val.isObject());
     742           0 :     return static_cast<RegExpStatics*>(val.toObject().as<RegExpStaticsObject>().getPrivate(/* nfixed = */ 1));
     743             : }
     744             : 
     745             : /* static */ NativeObject*
     746       61816 : GlobalObject::getIntrinsicsHolder(JSContext* cx, Handle<GlobalObject*> global)
     747             : {
     748       61816 :     Value slot = global->getReservedSlot(INTRINSICS);
     749       61816 :     MOZ_ASSERT(slot.isUndefined() || slot.isObject());
     750             : 
     751       61816 :     if (slot.isObject())
     752       61505 :         return &slot.toObject().as<NativeObject>();
     753             : 
     754         622 :     Rooted<NativeObject*> intrinsicsHolder(cx);
     755         311 :     bool isSelfHostingGlobal = cx->runtime()->isSelfHostingGlobal(global);
     756         311 :     if (isSelfHostingGlobal) {
     757           3 :         intrinsicsHolder = global;
     758             :     } else {
     759         308 :         intrinsicsHolder = NewObjectWithGivenProto<PlainObject>(cx, nullptr, TenuredObject);
     760         308 :         if (!intrinsicsHolder)
     761           0 :             return nullptr;
     762             :     }
     763             : 
     764             :     /* Define a property 'global' with the current global as its value. */
     765         622 :     RootedValue globalValue(cx, ObjectValue(*global));
     766         311 :     if (!DefineProperty(cx, intrinsicsHolder, cx->names().global, globalValue,
     767             :                         nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
     768             :     {
     769           0 :         return nullptr;
     770             :     }
     771             : 
     772             :     // Install the intrinsics holder in the intrinsics.
     773         311 :     global->setReservedSlot(INTRINSICS, ObjectValue(*intrinsicsHolder));
     774         311 :     return intrinsicsHolder;
     775             : }
     776             : 
     777             : /* static */ bool
     778       20912 : GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
     779             :                                     HandlePropertyName selfHostedName, HandleAtom name,
     780             :                                     unsigned nargs, MutableHandleValue funVal)
     781             : {
     782       20912 :     bool exists = false;
     783       20912 :     if (!GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal, &exists))
     784           0 :         return false;
     785       20912 :     if (exists) {
     786        2124 :         RootedFunction fun(cx, &funVal.toObject().as<JSFunction>());
     787        1062 :         if (fun->explicitName() == name)
     788         883 :             return true;
     789             : 
     790         179 :         if (fun->explicitName() == selfHostedName) {
     791             :             // This function was initially cloned because it was called by
     792             :             // other self-hosted code, so the clone kept its self-hosted name,
     793             :             // instead of getting the name it's intended to have in content
     794             :             // compartments. This can happen when a lazy builtin is initialized
     795             :             // after self-hosted code for another builtin used the same
     796             :             // function. In that case, we need to change the function's name,
     797             :             // which is ok because it can't have been exposed to content
     798             :             // before.
     799           0 :             fun->initAtom(name);
     800           0 :             return true;
     801             :         }
     802             : 
     803             : 
     804             :         // The function might be installed multiple times on the same or
     805             :         // different builtins, under different property names, so its name
     806             :         // might be neither "selfHostedName" nor "name". In that case, its
     807             :         // canonical name must've been set using the `_SetCanonicalName`
     808             :         // intrinsic.
     809         179 :         cx->runtime()->assertSelfHostedFunctionHasCanonicalName(cx, selfHostedName);
     810         179 :         return true;
     811             :     }
     812             : 
     813       39701 :     RootedFunction fun(cx);
     814       19850 :     if (!cx->runtime()->createLazySelfHostedFunctionClone(cx, selfHostedName, name, nargs,
     815             :                                                           /* proto = */ nullptr,
     816             :                                                           SingletonObject, &fun))
     817             :     {
     818           0 :         return false;
     819             :     }
     820       19851 :     funVal.setObject(*fun);
     821             : 
     822       19851 :     return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);
     823             : }
     824             : 
     825             : /* static */ bool
     826       22132 : GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
     827             :                                 HandlePropertyName name, HandleValue value)
     828             : {
     829       44264 :     RootedNativeObject holder(cx, GlobalObject::getIntrinsicsHolder(cx, global));
     830       22132 :     if (!holder)
     831           0 :         return false;
     832             : 
     833       22132 :     uint32_t slot = holder->slotSpan();
     834       44264 :     RootedShape last(cx, holder->lastProperty());
     835       44264 :     Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
     836             : 
     837       44264 :     RootedId id(cx, NameToId(name));
     838       44264 :     Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
     839       22132 :     Shape* shape = cx->zone()->propertyTree().getChild(cx, last, child);
     840       22132 :     if (!shape)
     841           0 :         return false;
     842             : 
     843       22132 :     if (!holder->setLastProperty(cx, shape))
     844           0 :         return false;
     845             : 
     846       22132 :     holder->setSlot(shape->slot(), value);
     847       22132 :     return true;
     848             : }
     849             : 
     850             : /* static */ bool
     851           0 : GlobalObject::ensureModulePrototypesCreated(JSContext *cx, Handle<GlobalObject*> global)
     852             : {
     853           0 :     return getOrCreateObject(cx, global, MODULE_PROTO, initModuleProto) &&
     854           0 :            getOrCreateObject(cx, global, IMPORT_ENTRY_PROTO, initImportEntryProto) &&
     855           0 :            getOrCreateObject(cx, global, EXPORT_ENTRY_PROTO, initExportEntryProto);
     856             : }

Generated by: LCOV version 1.13