Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetLength(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
        Assert(callInfo.Count == 2);

        int64 length;
        Var iterable = args.Values[1];

        TypedArrayBase *typedArrayBase = nullptr;
        Assert(!JavascriptArray::Is(iterable));

        if (TypedArrayBase::Is(iterable))
        {
            typedArrayBase = TypedArrayBase::FromVar(iterable);
            if (typedArrayBase->IsDetachedBuffer())
            {
                JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
            }

            length = typedArrayBase->GetLength();
        }
        else
        {
            length = JavascriptConversion::ToLength(JavascriptOperators::OP_GetLength(iterable, scriptContext), scriptContext);
        }

        return JavascriptNumber::ToVar(length, scriptContext);
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArraySpeciesCreate(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
        AssertOrFailFast(args.Info.Count == 3);

        int64 length64 = JavascriptConversion::ToLength(args.Values[2], scriptContext);
        if (length64 > UINT_MAX)
        {
            JavascriptError::ThrowRangeError(scriptContext, JSERR_ArrayLengthConstructIncorrect);
        }

        uint32 length = static_cast<uint32>(length64);

        bool isBuiltinArrayCtor = true;
        RecyclableObject * newObj = JavascriptArray::ArraySpeciesCreate(args.Values[1], length, scriptContext, nullptr, nullptr, &isBuiltinArrayCtor);
        nullptr;

        if (newObj == nullptr)
        {
            newObj = scriptContext->GetLibrary()->CreateArray(length);
        }
        else
        {
#if ENABLE_COPYONACCESS_ARRAY
            JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
#endif
        }

        return newObj;
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        AssertOrFailFast(args.Info.Count >= 3 && JavascriptString::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2]));

        JavascriptLibrary * library = scriptContext->GetLibrary();

        // retrieves arguments
        JavascriptString* methodName = JavascriptString::FromVar(args.Values[1]);
        JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]);

        // Set the function's display name, as the function we pass in argument are anonym.
        func->GetFunctionProxy()->SetIsPublicLibraryCode();
        func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0);

        DynamicObject* chakraLibraryObject = GetPrototypeFromName(PropertyIds::__chakraLibrary, scriptContext);
        PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext);

        // Link the function to __chakraLibrary.
        ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy());
        scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();

        Assert(scriptFunction->HasFunctionBody());
        scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();

        scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr);

        library->AddMember(chakraLibraryObject, functionIdentifier, scriptFunction);

        //Don't need to return anything
        return library->GetUndefined();
    }
    Var EngineInterfaceObject::Entry_TagPublicLibraryCode(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        if (callInfo.Count >= 2 && JavascriptFunction::Is(args.Values[1]))
        {
            JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[1]);
            func->GetFunctionProxy()->SetIsPublicLibraryCode();

            if (callInfo.Count >= 3 && JavascriptString::Is(args.Values[2]))
            {
                JavascriptString* customFunctionName = JavascriptString::FromVar(args.Values[2]);
                // tagPublicFunction("Intl.Collator", Collator); in Intl.js calls TagPublicLibraryCode the expected name is Collator so we need to calculate the offset
                const wchar_t * shortName = wcsrchr(customFunctionName->GetString(), L'.');
                uint shortNameOffset = 0;
                if (shortName != nullptr)
                {
                    // JavascriptString length is bounded by uint max
                    shortName++;
                    shortNameOffset = static_cast<uint>(shortName - customFunctionName->GetString());
                }
                func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(customFunctionName->GetString(), customFunctionName->GetLength(), shortNameOffset);
            }

            return func;
        }

        return scriptContext->GetLibrary()->GetUndefined();
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetIteratorPrototype(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        Assert(callInfo.Count == 1);

        return scriptContext->GetLibrary()->iteratorPrototype;
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
        AssertOrFailFast(args.Info.Count == 4);

        RecyclableObject * obj = RecyclableObject::FromVar(args.Values[1]);
        double index = JavascriptConversion::ToInteger(args.Values[2], scriptContext);
        AssertOrFailFast(index >= 0);
        JavascriptArray::BigIndex bigIndex(static_cast<uint64>(index));
        Var item = args.Values[3];

        JavascriptArray::CreateDataPropertyOrThrow(obj, bigIndex, item, scriptContext);
        return scriptContext->GetLibrary()->GetTrue();
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_InitInternalProperties(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        DynamicObject* obj = DynamicObject::FromVar(args.Values[1]);
        unsigned propCount = TaggedInt::ToUInt32(args.Values[2]);

        Assert(callInfo.Count == 3 + propCount);

        for (unsigned i = 0; i < propCount; i++)
        {
            JavascriptString *propName = JavascriptString::FromVar(args.Values[i + 3]);
            obj->SetPropertyWithAttributes(JavascriptOperators::GetPropertyId(propName, scriptContext), scriptContext->GetLibrary()->GetNull(), PropertyWritable, nullptr);
        }

        return obj;
    }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToIntegerFunction(RecyclableObject * function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
        Assert(args.Info.Count == 2);

        Var value = args.Values[1];
        if (JavascriptOperators::IsUndefinedOrNull(value))
        {
            return TaggedInt::ToVarUnchecked(0);
        }
        else if (TaggedInt::Is(value))
        {
            return value;
        }

        return JavascriptNumber::ToVarNoCheck(JavascriptConversion::ToInteger(value, scriptContext), scriptContext);
    }
    Var EngineInterfaceObject::Entry_LogDebugMessage(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

#if DBG
        if (callInfo.Count < 2 || !JavascriptString::Is(args.Values[1]))
        {
            return scriptContext->GetLibrary()->GetUndefined();
        }

        JavascriptString* message = JavascriptString::FromVar(args.Values[1]);

        Output::Print(message->GetString());
        Output::Flush();
#endif

        return scriptContext->GetLibrary()->GetUndefined();
    }
    Var EngineInterfaceObject::Entry_GetErrorMessage(RecyclableObject *function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        if (callInfo.Count < 2)
        {
            return scriptContext->GetLibrary()->GetUndefined();
        }

        int hr = Js::JavascriptConversion::ToInt32(args[1], scriptContext);
        int resourceId;

        switch(hr)
        {
        case ASYNCERR_NoErrorInErrorState:
            resourceId = 5200;
            break;
        case ASYNCERR_InvalidStatusArg:
            resourceId = 5201;
            break;
        case ASYNCERR_InvalidSenderArg:
            resourceId = 5202;
            break;
        default:
            AssertMsg(false, "Invalid HRESULT passed to GetErrorMessage. This shouldn't come from Promise.js - who called us?");
            return scriptContext->GetLibrary()->GetUndefined();
        }

        const int strLength = 1024;
        OLECHAR errorString[strLength];

        if(FGetResourceString(resourceId, errorString, strLength))
        {
            return Js::JavascriptString::NewCopySz(errorString, scriptContext);
        }

        AssertMsg(false, "FGetResourceString returned false.");
        return scriptContext->GetLibrary()->GetUndefined();
    }
 Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToLengthFunction(RecyclableObject * function, CallInfo callInfo, ...)
 {
     EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
     Assert(args.Info.Count == 2);
     return JavascriptNumber::ToVar(JavascriptConversion::ToLength(args.Values[1], scriptContext), scriptContext);
 }
    Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterFunction(RecyclableObject* function, CallInfo callInfo, ...)
    {
        EngineInterfaceObject_CommonFunctionProlog(function, callInfo);

        AssertOrFailFast(args.Info.Count >= 3 && JavascriptObject::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2]));

        JavascriptLibrary * library = scriptContext->GetLibrary();

        // retrieves arguments
        RecyclableObject* funcInfo = nullptr;
        if (!JavascriptConversion::ToObject(args.Values[1], scriptContext, &funcInfo))
        {
            JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Object.assign"));
        }

        Var classNameProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::className, scriptContext);
        Var methodNameProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::methodName, scriptContext);
        Var argumentsCountProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::argumentsCount, scriptContext);
        Var forceInlineProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::forceInline, scriptContext);
        Var aliasProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::alias, scriptContext);

        Assert(JavascriptString::Is(classNameProperty));
        Assert(JavascriptString::Is(methodNameProperty));
        Assert(TaggedInt::Is(argumentsCountProperty));

        JavascriptString* className = JavascriptString::FromVar(classNameProperty);
        JavascriptString* methodName = JavascriptString::FromVar(methodNameProperty);
        int argumentsCount = TaggedInt::ToInt32(argumentsCountProperty);

        BOOL forceInline = JavascriptConversion::ToBoolean(forceInlineProperty, scriptContext);

        JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]);

        // Set the function's display name, as the function we pass in argument are anonym.
        func->GetFunctionProxy()->SetIsPublicLibraryCode();
        func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0);

        DynamicObject* prototype = GetPrototypeFromName(JavascriptOperators::GetPropertyId(className, scriptContext), scriptContext);
        PropertyIds functionIdentifier = methodName->BufferEquals(_u("Symbol.iterator"), 15)? PropertyIds::_symbolIterator :
            JavascriptOperators::GetPropertyId(methodName, scriptContext);

        // Link the function to the prototype.
        ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy());
        scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode();

        if (forceInline)
        {
            Assert(scriptFunction->HasFunctionBody());
            scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline();
        }
        scriptFunction->SetPropertyWithAttributes(PropertyIds::length, TaggedInt::ToVarUnchecked(argumentsCount), PropertyConfigurable, nullptr);

        scriptFunction->SetConfigurable(PropertyIds::prototype, true);
        scriptFunction->DeleteProperty(PropertyIds::prototype, Js::PropertyOperationFlags::PropertyOperation_None);

        scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr);

        library->AddMember(prototype, functionIdentifier, scriptFunction);

        RecordCommonNativeInterfaceBuiltIns(functionIdentifier, scriptContext, scriptFunction);

        if (!JavascriptOperators::IsUndefinedOrNull(aliasProperty))
        {
            JavascriptString * alias = JavascriptConversion::ToString(aliasProperty, scriptContext);
            // Cannot do a string to property id search here, Symbol.* have different hashing mechanism, so resort to this str compare
            PropertyIds aliasFunctionIdentifier = alias->BufferEquals(_u("Symbol.iterator"), 15) ? PropertyIds::_symbolIterator :
                JavascriptOperators::GetPropertyId(alias, scriptContext);
            library->AddMember(prototype, aliasFunctionIdentifier, scriptFunction);
        }

        if (prototype == library->arrayPrototype)
        {
            RecordDefaultIteratorFunctions(functionIdentifier, scriptContext, scriptFunction);
        }

        //Don't need to return anything
        return library->GetUndefined();
    }