/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "vm/GlobalObject.h"

#include "jscntxt.h"
#include "jsdate.h"
#include "jsexn.h"
#include "jsfriendapi.h"
#include "jsmath.h"
#include "json.h"
#include "jsprototypes.h"
#include "jsweakmap.h"

#include "builtin/AtomicsObject.h"
#include "builtin/Eval.h"
#if EXPOSE_INTL_API
# include "builtin/Intl.h"
#endif
#include "builtin/MapObject.h"
#include "builtin/ModuleObject.h"
#include "builtin/Object.h"
#include "builtin/RegExp.h"
#include "builtin/SIMD.h"
#include "builtin/SymbolObject.h"
#include "builtin/TypedObject.h"
#include "builtin/WeakMapObject.h"
#include "builtin/WeakSetObject.h"
#include "vm/HelperThreads.h"
#include "vm/PIC.h"
#include "vm/RegExpStatics.h"
#include "vm/RegExpStaticsObject.h"
#include "vm/ScopeObject.h"
#include "vm/StopIterationObject.h"

#include "jscompartmentinlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"

#include "vm/NativeObject-inl.h"

using namespace js;

struct ProtoTableEntry {
    const Class* clasp;
    ClassInitializerOp init;
};

namespace js {

#define DECLARE_PROTOTYPE_CLASS_INIT(name,code,init,clasp) \
    extern JSObject* init(JSContext* cx, Handle<JSObject*> obj);
JS_FOR_EACH_PROTOTYPE(DECLARE_PROTOTYPE_CLASS_INIT)
#undef DECLARE_PROTOTYPE_CLASS_INIT

} // namespace js

JSObject*
js::InitViaClassSpec(JSContext* cx, Handle<JSObject*> obj)
{
    MOZ_CRASH("InitViaClassSpec() should not be called.");
}

static const ProtoTableEntry protoTable[JSProto_LIMIT] = {
#define INIT_FUNC(name,code,init,clasp) { clasp, init },
#define INIT_FUNC_DUMMY(name,code,init,clasp) { nullptr, nullptr },
    JS_FOR_PROTOTYPES(INIT_FUNC, INIT_FUNC_DUMMY)
#undef INIT_FUNC_DUMMY
#undef INIT_FUNC
};

JS_FRIEND_API(const js::Class*)
js::ProtoKeyToClass(JSProtoKey key)
{
    MOZ_ASSERT(key < JSProto_LIMIT);
    return protoTable[key].clasp;
}

// This method is not in the header file to avoid having to include
// TypedObject.h from GlobalObject.h. It is not generally perf
// sensitive.
TypedObjectModuleObject&
js::GlobalObject::getTypedObjectModule() const {
    Value v = getConstructor(JSProto_TypedObject);
    // only gets called from contexts where TypedObject must be initialized
    MOZ_ASSERT(v.isObject());
    return v.toObject().as<TypedObjectModuleObject>();
}

/* static */ bool
GlobalObject::ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
{
    if (global->isStandardClassResolved(key))
        return true;
    return resolveConstructor(cx, global, key);
}

/* static*/ bool
GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
{
    MOZ_ASSERT(!global->isStandardClassResolved(key));

    // There are two different kinds of initialization hooks. One of them is
    // the class js::InitFoo hook, defined in a JSProtoKey-keyed table at the
    // top of this file. The other lives in the ClassSpec for classes that
    // define it. Classes may use one or the other, but not both.
    ClassInitializerOp init = protoTable[key].init;
    if (init == InitViaClassSpec)
        init = nullptr;

    const Class* clasp = ProtoKeyToClass(key);
    if (!init && !clasp)
        return true;  // JSProto_Null or a compile-time-disabled feature.

    // Some classes have no init routine, which means that they're disabled at
    // compile-time. We could try to enforce that callers never pass such keys
    // to resolveConstructor, but that would cramp the style of consumers like
    // GlobalObject::initStandardClasses that want to just carpet-bomb-call
    // ensureConstructor with every JSProtoKey. So it's easier to just handle
    // it here.
    bool haveSpec = clasp && clasp->spec.defined();
    if (!init && !haveSpec)
        return true;

    // See if there's an old-style initialization hook.
    if (init) {
        MOZ_ASSERT(!haveSpec);
        return init(cx, global);
    }

    //
    // Ok, we're doing it with a class spec.
    //

    // We need to create the prototype first, and immediately stash it in the
    // slot. This is so the following bootstrap ordering is possible:
    // * Object.prototype
    // * Function.prototype
    // * Function
    // * Object
    //
    // We get the above when Object is resolved before Function. If Function
    // is resolved before Object, we'll end up re-entering resolveConstructor
    // for Function, which is a problem. So if Function is being resolved before
    // Object.prototype exists, we just resolve Object instead, since we know that
    // Function will also be resolved before we return.
    if (key == JSProto_Function && global->getPrototype(JSProto_Object).isUndefined())
        return resolveConstructor(cx, global, JSProto_Object);

    // We don't always have a prototype (i.e. Math and JSON). If we don't,
    // |createPrototype|, |prototypeFunctions|, and |prototypeProperties|
    // should all be null.
    RootedObject proto(cx);
    if (clasp->spec.createPrototypeHook()) {
        proto = clasp->spec.createPrototypeHook()(cx, key);
        if (!proto)
            return false;

        global->setPrototype(key, ObjectValue(*proto));
    }

    // Create the constructor.
    RootedObject ctor(cx, clasp->spec.createConstructorHook()(cx, key));
    if (!ctor)
        return false;

    RootedId id(cx, NameToId(ClassName(key, cx)));
    if (clasp->spec.shouldDefineConstructor()) {
        if (!global->addDataProperty(cx, id, constructorPropertySlot(key), 0))
            return false;
    }

    global->setConstructor(key, ObjectValue(*ctor));
    global->setConstructorPropertySlot(key, ObjectValue(*ctor));

    // Define any specified functions and properties, unless we're a dependent
    // standard class (in which case they live on the prototype).
    if (!StandardClassIsDependent(key)) {
        if (const JSFunctionSpec* funs = clasp->spec.prototypeFunctions()) {
            if (!JS_DefineFunctions(cx, proto, funs, DontDefineLateProperties))
                return false;
        }
        if (const JSPropertySpec* props = clasp->spec.prototypeProperties()) {
            if (!JS_DefineProperties(cx, proto, props))
                return false;
        }
        if (const JSFunctionSpec* funs = clasp->spec.constructorFunctions()) {
            if (!JS_DefineFunctions(cx, ctor, funs, DontDefineLateProperties))
                return false;
        }
        if (const JSPropertySpec* props = clasp->spec.constructorProperties()) {
            if (!JS_DefineProperties(cx, ctor, props))
                return false;
        }
    }

    // If the prototype exists, link it with the constructor.
    if (proto && !LinkConstructorAndPrototype(cx, ctor, proto))
        return false;

    // Call the post-initialization hook, if provided.
    if (clasp->spec.finishInitHook() && !clasp->spec.finishInitHook()(cx, ctor, proto))
        return false;

    if (clasp->spec.shouldDefineConstructor()) {
        // Stash type information, so that what we do here is equivalent to
        // initBuiltinConstructor.
        AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
    }

    return true;
}

/* static */ bool
GlobalObject::initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
                                     JSProtoKey key, HandleObject ctor, HandleObject proto)
{
    MOZ_ASSERT(!global->empty()); // reserved slots already allocated
    MOZ_ASSERT(key != JSProto_Null);
    MOZ_ASSERT(ctor);
    MOZ_ASSERT(proto);

    RootedId id(cx, NameToId(ClassName(key, cx)));
    MOZ_ASSERT(!global->lookup(cx, id));

    if (!global->addDataProperty(cx, id, constructorPropertySlot(key), 0))
        return false;

    global->setConstructor(key, ObjectValue(*ctor));
    global->setPrototype(key, ObjectValue(*proto));
    global->setConstructorPropertySlot(key, ObjectValue(*ctor));

    AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
    return true;
}

GlobalObject*
GlobalObject::createInternal(JSContext* cx, const Class* clasp)
{
    MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
    MOZ_ASSERT(clasp->trace == JS_GlobalObjectTraceHook);

    JSObject* obj = NewObjectWithGivenProto(cx, clasp, nullptr, SingletonObject);
    if (!obj)
        return nullptr;

    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
    MOZ_ASSERT(global->isUnqualifiedVarObj());

    // Initialize the private slot to null if present, as GC can call class
    // hooks before the caller gets to set this to a non-garbage value.
    if (clasp->flags & JSCLASS_HAS_PRIVATE)
        global->setPrivate(nullptr);

    Rooted<ClonedBlockObject*> lexical(cx, ClonedBlockObject::createGlobal(cx, global));
    if (!lexical)
        return nullptr;
    global->setReservedSlot(LEXICAL_SCOPE, ObjectValue(*lexical));

    cx->compartment()->initGlobal(*global);

    if (!global->setQualifiedVarObj(cx))
        return nullptr;
    if (!global->setDelegate(cx))
        return nullptr;

    return global;
}

GlobalObject*
GlobalObject::new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
                   JS::OnNewGlobalHookOption hookOption,
                   const JS::CompartmentOptions& options)
{
    MOZ_ASSERT(!cx->isExceptionPending());
    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));

    JSRuntime* rt = cx->runtime();

    Zone* zone;
    if (options.zoneSpecifier() == JS::SystemZone)
        zone = rt->gc.systemZone;
    else if (options.zoneSpecifier() == JS::FreshZone)
        zone = nullptr;
    else
        zone = static_cast<Zone*>(options.zonePointer());

    JSCompartment* compartment = NewCompartment(cx, zone, principals, options);
    if (!compartment)
        return nullptr;

    // Lazily create the system zone.
    if (!rt->gc.systemZone && options.zoneSpecifier() == JS::SystemZone) {
        rt->gc.systemZone = compartment->zone();
        rt->gc.systemZone->isSystem = true;
    }

    Rooted<GlobalObject*> global(cx);
    {
        AutoCompartment ac(cx, compartment);
        global = GlobalObject::createInternal(cx, clasp);
        if (!global)
            return nullptr;
    }

    if (hookOption == JS::FireOnNewGlobalHook)
        JS_FireOnNewGlobalObject(cx, global);

    return global;
}

ClonedBlockObject&
GlobalObject::lexicalScope() const
{
    return getReservedSlot(LEXICAL_SCOPE).toObject().as<ClonedBlockObject>();
}

/* static */ bool
GlobalObject::getOrCreateEval(JSContext* cx, Handle<GlobalObject*> global,
                              MutableHandleObject eval)
{
    if (!global->getOrCreateObjectPrototype(cx))
        return false;
    eval.set(&global->getSlot(EVAL).toObject());
    return true;
}

bool
GlobalObject::valueIsEval(Value val)
{
    Value eval = getSlot(EVAL);
    return eval.isObject() && eval == val;
}

/* static */ bool
GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global)
{
    /* Define a top-level property 'undefined' with the undefined value. */
    if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
                        nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING))
    {
        return false;
    }

    for (size_t k = 0; k < JSProto_LIMIT; ++k) {
        if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
            return false;
    }
    return true;
}

/**
 * Initializes a builtin constructor and its prototype without defining any
 * properties or functions on it.
 *
 * Used in self-hosting to install the few builtin constructors required by
 * self-hosted builtins.
 */
static bool
InitBareBuiltinCtor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey protoKey)
{
    MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(global));
    const Class* clasp = ProtoKeyToClass(protoKey);
    RootedObject proto(cx);
    proto = clasp->spec.createPrototypeHook()(cx, protoKey);
    if (!proto)
        return false;

    RootedObject ctor(cx, clasp->spec.createConstructorHook()(cx, protoKey));
    if (!ctor)
        return false;

    return GlobalObject::initBuiltinConstructor(cx, global, protoKey, ctor, proto);
}

/**
 * The self-hosting global only gets a small subset of all standard classes.
 * Even those are only created as bare constructors without any properties
 * or functions.
 */
/* static */ bool
GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> global,
                                      const JSFunctionSpec* builtins)
{
    // Define a top-level property 'undefined' with the undefined value.
    if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
                        nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
    {
        return false;
    }

    // Define a top-level property 'std_iterator' with the name of the method
    // used by for-of loops to create an iterator.
    RootedValue std_iterator(cx);
    std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator));
    if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator,
                           JSPROP_PERMANENT | JSPROP_READONLY))
    {
        return false;
    }

    RootedValue std_species(cx);
    std_species.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::species));
    if (!JS_DefineProperty(cx, global, "std_species", std_species,
                           JSPROP_PERMANENT | JSPROP_READONLY))
    {
        return false;
    }

    return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
           InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
           InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
           InitBareBuiltinCtor(cx, global, JSProto_Uint32Array) &&
           InitBareWeakMapCtor(cx, global) &&
           InitStopIterationClass(cx, global) &&
           InitSelfHostingCollectionIteratorFunctions(cx, global) &&
           JS_DefineFunctions(cx, global, builtins);
}

#if defined(COBALT)
/* static */ bool
GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global)
{
    /*
     * For Cobalt, do not cache the value. Allow the callback to be triggered
     * every time so we can do proper CSP reporting.
     */
    JSCSPEvalChecker allows = cx->runtime()->securityCallbacks->contentSecurityPolicyAllows;
    return !allows || allows(cx);
}
#else

/* static */ bool
GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx, Handle<GlobalObject*> global)
{
    HeapSlot &v = global->getSlotRef(RUNTIME_CODEGEN_ENABLED);
    if (v.isUndefined()) {
        /*
         * If there are callbacks, make sure that the CSP callback is installed
         * and that it permits runtime code generation, then cache the result.
         */
        JSCSPEvalChecker allows = cx->runtime()->securityCallbacks->contentSecurityPolicyAllows;
        Value boolValue = BooleanValue(!allows || allows(cx));
        v.set(global, HeapSlot::Slot, RUNTIME_CODEGEN_ENABLED, boolValue);
    }
    return !v.isFalse();
}
#endif

/* static */ bool
GlobalObject::warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag,
                            unsigned errorNumber)
{
    Rooted<GlobalObject*> global(cx, &obj->global());
    HeapSlot& v = global->getSlotRef(WARNED_ONCE_FLAGS);
    MOZ_ASSERT_IF(!v.isUndefined(), v.toInt32());
    int32_t flags = v.isUndefined() ? 0 : v.toInt32();
    if (!(flags & flag)) {
        if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
                                          errorNumber))
        {
            return false;
        }
        if (v.isUndefined())
            v.init(global, HeapSlot::Slot, WARNED_ONCE_FLAGS, Int32Value(flags | flag));
        else
            v.set(global, HeapSlot::Slot, WARNED_ONCE_FLAGS, Int32Value(flags | flag));
    }
    return true;
}

JSFunction*
GlobalObject::createConstructor(JSContext* cx, Native ctor, JSAtom* nameArg, unsigned length,
                                gc::AllocKind kind, const JSJitInfo* jitInfo)
{
    RootedAtom name(cx, nameArg);
    JSFunction* fun = NewNativeConstructor(cx, ctor, length, name, kind);
    if (!fun)
        return nullptr;

    if (jitInfo)
        fun->setJitInfo(jitInfo);

    return fun;
}

static NativeObject*
CreateBlankProto(JSContext* cx, const Class* clasp, HandleObject proto, HandleObject global)
{
    MOZ_ASSERT(clasp != &JSFunction::class_);

    RootedNativeObject blankProto(cx, NewNativeObjectWithGivenProto(cx, clasp, proto,
                                                                    SingletonObject));
    if (!blankProto || !blankProto->setDelegate(cx))
        return nullptr;

    return blankProto;
}

NativeObject*
GlobalObject::createBlankPrototype(JSContext* cx, const Class* clasp)
{
    Rooted<GlobalObject*> self(cx, this);
    RootedObject objectProto(cx, getOrCreateObjectPrototype(cx));
    if (!objectProto)
        return nullptr;

    return CreateBlankProto(cx, clasp, objectProto, self);
}

NativeObject*
GlobalObject::createBlankPrototypeInheriting(JSContext* cx, const Class* clasp, HandleObject proto)
{
    Rooted<GlobalObject*> self(cx, this);
    return CreateBlankProto(cx, clasp, proto, self);
}

bool
js::LinkConstructorAndPrototype(JSContext* cx, JSObject* ctor_, JSObject* proto_)
{
    RootedObject ctor(cx, ctor_), proto(cx, proto_);

    RootedValue protoVal(cx, ObjectValue(*proto));
    RootedValue ctorVal(cx, ObjectValue(*ctor));

    return DefineProperty(cx, ctor, cx->names().prototype, protoVal,
                          nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY) &&
           DefineProperty(cx, proto, cx->names().constructor, ctorVal,
                          nullptr, nullptr, 0);
}

bool
js::DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
                                 const JSPropertySpec* ps, const JSFunctionSpec* fs)
{
    if (ps && !JS_DefineProperties(cx, obj, ps))
        return false;
    if (fs && !JS_DefineFunctions(cx, obj, fs))
        return false;
    return true;
}

static void
GlobalDebuggees_finalize(FreeOp* fop, JSObject* obj)
{
    fop->delete_((GlobalObject::DebuggerVector*) obj->as<NativeObject>().getPrivate());
}

static const Class
GlobalDebuggees_class = {
    "GlobalDebuggee", JSCLASS_HAS_PRIVATE,
    nullptr, nullptr, nullptr, nullptr,
    nullptr, nullptr, nullptr, GlobalDebuggees_finalize
};

GlobalObject::DebuggerVector*
GlobalObject::getDebuggers() const
{
    Value debuggers = getReservedSlot(DEBUGGERS);
    if (debuggers.isUndefined())
        return nullptr;
    MOZ_ASSERT(debuggers.toObject().getClass() == &GlobalDebuggees_class);
    return (DebuggerVector*) debuggers.toObject().as<NativeObject>().getPrivate();
}

/* static */ GlobalObject::DebuggerVector*
GlobalObject::getOrCreateDebuggers(JSContext* cx, Handle<GlobalObject*> global)
{
    assertSameCompartment(cx, global);
    DebuggerVector* debuggers = global->getDebuggers();
    if (debuggers)
        return debuggers;

    NativeObject* obj = NewNativeObjectWithGivenProto(cx, &GlobalDebuggees_class, nullptr);
    if (!obj)
        return nullptr;
    debuggers = cx->new_<DebuggerVector>();
    if (!debuggers)
        return nullptr;
    obj->setPrivate(debuggers);
    global->setReservedSlot(DEBUGGERS, ObjectValue(*obj));
    return debuggers;
}

/* static */ NativeObject*
GlobalObject::getOrCreateForOfPICObject(JSContext* cx, Handle<GlobalObject*> global)
{
    assertSameCompartment(cx, global);
    NativeObject* forOfPIC = global->getForOfPICObject();
    if (forOfPIC)
        return forOfPIC;

    forOfPIC = ForOfPIC::createForOfPICObject(cx, global);
    if (!forOfPIC)
        return nullptr;
    global->setReservedSlot(FOR_OF_PIC_CHAIN, ObjectValue(*forOfPIC));
    return forOfPIC;
}

bool
GlobalObject::hasRegExpStatics() const
{
    return !getSlot(REGEXP_STATICS).isUndefined();
}

RegExpStatics*
GlobalObject::getRegExpStatics(ExclusiveContext* cx) const
{
    MOZ_ASSERT(cx);
    Rooted<GlobalObject*> self(cx, const_cast<GlobalObject*>(this));

    RegExpStaticsObject* resObj = nullptr;
    const Value& val = this->getSlot(REGEXP_STATICS);
    if (!val.isObject()) {
        MOZ_ASSERT(val.isUndefined());
        resObj = RegExpStatics::create(cx, self);
        if (!resObj)
            return nullptr;

        self->initSlot(REGEXP_STATICS, ObjectValue(*resObj));
    } else {
        resObj = &val.toObject().as<RegExpStaticsObject>();
    }
    return static_cast<RegExpStatics*>(resObj->getPrivate(/* nfixed = */ 1));
}

RegExpStatics*
GlobalObject::getAlreadyCreatedRegExpStatics() const
{
    const Value& val = this->getSlot(REGEXP_STATICS);
    MOZ_ASSERT(val.isObject());
    return static_cast<RegExpStatics*>(val.toObject().as<RegExpStaticsObject>().getPrivate(/* nfixed = */ 1));
}

/* static */ NativeObject*
GlobalObject::getIntrinsicsHolder(JSContext* cx, Handle<GlobalObject*> global)
{
    Value slot = global->getReservedSlot(INTRINSICS);
    MOZ_ASSERT(slot.isUndefined() || slot.isObject());

    if (slot.isObject())
        return &slot.toObject().as<NativeObject>();

    Rooted<NativeObject*> intrinsicsHolder(cx);
    bool isSelfHostingGlobal = cx->runtime()->isSelfHostingGlobal(global);
    if (isSelfHostingGlobal) {
        intrinsicsHolder = global;
    } else {
        intrinsicsHolder = NewObjectWithGivenProto<PlainObject>(cx, nullptr, TenuredObject);
        if (!intrinsicsHolder)
            return nullptr;
    }

    /* Define a property 'global' with the current global as its value. */
    RootedValue globalValue(cx, ObjectValue(*global));
    if (!DefineProperty(cx, intrinsicsHolder, cx->names().global, globalValue,
                        nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY))
    {
        return nullptr;
    }

    // Install the intrinsics holder in the intrinsics.
    global->setReservedSlot(INTRINSICS, ObjectValue(*intrinsicsHolder));
    return intrinsicsHolder;
}

/* static */ bool
GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
                                    HandlePropertyName selfHostedName, HandleAtom name,
                                    unsigned nargs, MutableHandleValue funVal)
{
    if (GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal))
        return true;

    JSFunction* fun =
        NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
                            name, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
    if (!fun)
        return false;
    fun->setIsSelfHostedBuiltin();
    fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
    funVal.setObject(*fun);

    return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);
}

/* static */ bool
GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
                                HandlePropertyName name, HandleValue value)
{
    RootedNativeObject holder(cx, GlobalObject::getIntrinsicsHolder(cx, global));
    if (!holder)
        return false;

    uint32_t slot = holder->slotSpan();
    RootedShape last(cx, holder->lastProperty());
    Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());

    RootedId id(cx, NameToId(name));
    Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
    Shape* shape = cx->compartment()->propertyTree.getChild(cx, last, child);
    if (!shape)
        return false;

    if (!holder->setLastProperty(cx, shape))
        return false;

    holder->setSlot(shape->slot(), value);
    return true;
}
