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 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();
    }