blob: 9a722f2fc60ec1f5f561ec19433ea10a65f79621 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"
#include "EngineInterfaceObject.h"
#include "JsBuiltInEngineInterfaceExtensionObject.h"
#include "Types/DeferredTypeHandler.h"
#ifdef ENABLE_JS_BUILTINS
#include "ByteCode/ByteCodeSerializer.h"
#include "errstr.h"
#include "ByteCode/ByteCodeDumper.h"
#define IfFailAssertMsgAndThrowHr(op, msg) \
if (FAILED(hr=(op))) \
{ \
AssertMsg(false, msg); \
JavascriptError::MapAndThrowError(scriptContext, hr); \
} \
enum class IsTypeStatic : bool
{
prototype = false,
constructor = true,
object = true
};
namespace Js
{
JsBuiltInEngineInterfaceExtensionObject::JsBuiltInEngineInterfaceExtensionObject(ScriptContext * scriptContext) :
EngineExtensionObjectBase(EngineInterfaceExtensionKind_JsBuiltIn, scriptContext)
{
}
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterFunction));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterChakraLibraryFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetLength(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetLength));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetIteratorPrototype(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetIteratorPrototype));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_InitInternalProperties(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_InitInternalProperties));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ToLengthFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToLengthFunction));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ToIntegerFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToIntegerFunction));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ArraySpeciesCreate(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArraySpeciesCreate));
NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow));
void JsBuiltInEngineInterfaceExtensionObject::Initialize()
{
if (wasInitialized)
{
return;
}
JavascriptLibrary* library = scriptContext->GetLibrary();
DynamicObject* commonObject = library->GetEngineInterfaceObject()->GetCommonNativeInterfaces();
if (scriptContext->IsJsBuiltInEnabled())
{
Assert(library->GetEngineInterfaceObject() != nullptr);
builtInNativeInterfaces = DynamicObject::New(library->GetRecycler(),
DynamicType::New(scriptContext, TypeIds_Object, commonObject, nullptr,
DeferredTypeHandler<InitializeJsBuiltInNativeInterfaces>::GetDefaultInstance()));
library->AddMember(library->GetEngineInterfaceObject(), Js::PropertyIds::JsBuiltIn, builtInNativeInterfaces);
}
wasInitialized = true;
}
void JsBuiltInEngineInterfaceExtensionObject::InitializePrototypes(ScriptContext * scriptContext)
{
JavascriptLibrary* library = scriptContext->GetLibrary();
JavascriptString * methodName = JavascriptString::NewWithSz(_u("ArrayIterator"), scriptContext);
auto arrayIterator = JavascriptOperators::GetProperty(library->GetChakraLib(), JavascriptOperators::GetPropertyId(methodName, scriptContext), scriptContext);
library->arrayIteratorPrototype = VarTo<DynamicObject>(JavascriptOperators::GetProperty(VarTo<DynamicObject>(arrayIterator), PropertyIds::prototype, scriptContext));
library->arrayIteratorPrototypeBuiltinNextFunction = VarTo<JavascriptFunction>(JavascriptOperators::GetProperty(library->arrayIteratorPrototype, PropertyIds::next, scriptContext));
}
void JsBuiltInEngineInterfaceExtensionObject::InjectJsBuiltInLibraryCode(ScriptContext * scriptContext, JsBuiltInFile file)
{
JavascriptExceptionObject *pExceptionObject = nullptr;
FunctionBody* jsBuiltInByteCode = nullptr;
switch (file)
{
#define jsBuiltInByteCodeCase(class, type, obj) \
case (JsBuiltInFile::class##_##type): \
{ \
if (jsBuiltIn##class##_##type##Bytecode != nullptr) \
return; \
EnsureSourceInfo(); \
uint32 flags = fscrJsBuiltIn | (CONFIG_FLAG(CreateFunctionProxy) && !scriptContext->IsProfiling() ? fscrAllowFunctionProxy : 0); \
SRCINFO* hsi = sourceInfo; \
Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)js::Library_Bytecode_##class##_##type, nullptr, &jsBuiltIn##class##_##type##Bytecode); \
jsBuiltInByteCode = jsBuiltIn##class##_##type##Bytecode; \
break; \
}
JsBuiltIns(jsBuiltInByteCodeCase)
#undef jsBuiltInByteCodeCase
}
this->SetHasBytecode();
try {
AssertOrFailFast(jsBuiltInByteCode != nullptr);
Js::ScriptFunction *functionGlobal = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode);
// If we are in the debugger and doing a GetProperty of arguments, then Js Builtins code will be injected on-demand
// Since it is a cross site call, we marshall not only functionGlobal but also its entire prototype chain
// The prototype of functionGlobal will be shared by a normal Js function,
// so marshalling will inadvertently transition the entrypoint of the prototype to a crosssite entrypoint
// So we set the prototype to null here
functionGlobal->SetPrototype(scriptContext->GetLibrary()->nullValue);
#ifdef ENABLE_SCRIPT_PROFILING
// If we are profiling, we need to register the script to the profiler callback, so the script compiled event will be sent.
if (scriptContext->IsProfiling())
{
scriptContext->RegisterScript(functionGlobal->GetFunctionProxy());
}
#endif
#ifdef ENABLE_SCRIPT_DEBUGGING
// Mark we are profiling library code already, so that any initialization library code called here won't be reported to profiler.
// Also tell the debugger not to record events during intialization so that we don't leak information about initialization.
AutoInitLibraryCodeScope autoInitLibraryCodeScope(scriptContext);
#endif
Js::Var args[] = { scriptContext->GetLibrary()->GetUndefined(), scriptContext->GetLibrary()->GetEngineInterfaceObject() };
Js::CallInfo callInfo(Js::CallFlags_Value, _countof(args));
#if ENABLE_JS_REENTRANCY_CHECK
// Create a Reentrancy lock to make sure we correctly restore the lock at the end of BuiltIns initialization
JsReentLock lock(scriptContext->GetThreadContext());
// Clear ReentrancyLock bit as initialization code doesn't have any side effect
scriptContext->GetThreadContext()->SetNoJsReentrancy(false);
#endif
// specify which set of BuiltIns are currently being loaded
current = file;
// Clear disable implicit call bit as initialization code doesn't have any side effect
{
ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
scriptContext->GetThreadContext()->ClearDisableImplicitFlags();
JavascriptFunction::CallRootFunctionInScript(functionGlobal, Js::Arguments(callInfo, args));
Js::ScriptFunction *functionBuiltins = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode->GetNestedFunctionForExecution(0));
functionBuiltins->SetPrototype(scriptContext->GetLibrary()->nullValue);
JavascriptFunction::CallRootFunctionInScript(functionBuiltins, Js::Arguments(callInfo, args));
}
if (file == JsBuiltInFile::Array_prototype)
{
InitializePrototypes(scriptContext);
}
#if DBG_DUMP
if (PHASE_DUMP(Js::ByteCodePhase, functionGlobal->GetFunctionProxy()) && Js::Configuration::Global.flags.Verbose)
{
DumpByteCode();
}
#endif
}
catch (const JavascriptException& err)
{
pExceptionObject = err.GetAndClear();
}
if (pExceptionObject)
{
switch (file)
{
#define clearJsBuiltInByteCodeCase(class, type, obj) \
case (JsBuiltInFile::class##_##type): \
jsBuiltIn##class##_##type##Bytecode = nullptr;
break;
JsBuiltIns(clearJsBuiltInByteCodeCase)
#undef clearJsBuiltInByteCodeCase
}
jsBuiltInByteCode = nullptr;
if (pExceptionObject == ThreadContext::GetContextForCurrentThread()->GetPendingSOErrorObject())
{
JavascriptExceptionOperators::DoThrowCheckClone(pExceptionObject, scriptContext);
}
Js::Throw::FatalJsBuiltInError();
}
}
bool JsBuiltInEngineInterfaceExtensionObject::InitializeJsBuiltInNativeInterfaces(DynamicObject * builtInNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
{
int initSlotCapacity = 5; // for register{ChakraLibrary}Function, POSITIVE_INFINITY, NEGATIVE_INFINITY, and GetIteratorPrototype
typeHandler->Convert(builtInNativeInterfaces, mode, initSlotCapacity);
ScriptContext* scriptContext = builtInNativeInterfaces->GetScriptContext();
JavascriptLibrary* library = scriptContext->GetLibrary();
library->AddMember(builtInNativeInterfaces, PropertyIds::POSITIVE_INFINITY, library->GetPositiveInfinite());
library->AddMember(builtInNativeInterfaces, PropertyIds::NEGATIVE_INFINITY, library->GetNegativeInfinite());
library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerChakraLibraryFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterChakraLibraryFunction, 2);
library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterFunction, 2);
library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::GetIteratorPrototype, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetIteratorPrototype, 1);
builtInNativeInterfaces->SetHasNoEnumerableProperties(true);
return true;
}
#if DBG
void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode(JsBuiltInFile file)
{
Output::Print(_u("Dumping JS Built Ins Byte Code:\n"));
switch (file)
{
#define fileCase(class, type, obj) \
case class##_##type: \
Assert(this->jsBuiltIn##class##_##type##Bytecode != nullptr); \
Js::ByteCodeDumper::DumpRecursively(this->jsBuiltIn##class##_##type##Bytecode); \
break;
JsBuiltIns(fileCase)
#undef fileCase
}
}
void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode()
{
Output::Print(_u("Dumping JS Built Ins Byte Code:\n"));
#define dumpOne(class, type, obj) \
if (this->jsBuiltIn##class##_##type##Bytecode != nullptr) \
{ \
DumpByteCode(JsBuiltInFile::class##_##type); \
}
JsBuiltIns(dumpOne)
#undef dumpOne
}
#endif // DBG
void JsBuiltInEngineInterfaceExtensionObject::EnsureSourceInfo()
{
if (sourceInfo == nullptr)
{
SourceContextInfo* sourceContextInfo = RecyclerNewStructZ(scriptContext->GetRecycler(), SourceContextInfo);
sourceContextInfo->dwHostSourceContext = Js::Constants::JsBuiltInSourceContext;
sourceContextInfo->isHostDynamicDocument = true;
sourceContextInfo->sourceContextId = Js::Constants::JsBuiltInSourceContextId;
Assert(sourceContextInfo != nullptr);
SRCINFO si;
memset((void*)&si, 0, sizeof(si));
si.sourceContextInfo = sourceContextInfo;
sourceInfo = scriptContext->AddHostSrcInfo(&si);
}
}
Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
AssertOrFailFast(args.Info.Count >= 3 && VarIs<JavascriptString>(args.Values[1]) && VarIs<ScriptFunction>(args.Values[2]));
JavascriptLibrary * library = scriptContext->GetLibrary();
JavascriptString* methodName = UnsafeVarTo<JavascriptString>(args.Values[1]);
// chakra library functions, since they aren't public, can be constructors (__chakraLibrary.ArrayIterator is one)
ScriptFunction* func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(
UnsafeVarTo<ScriptFunction>(args.Values[2]),
methodName,
true /* isConstructor */,
true /* isJsBuiltIn */,
false /* isPublic */
);
PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext);
library->AddMember(library->GetChakraLib(), functionIdentifier, func);
//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 && VarIs<ScriptFunction>(args.Values[2]));
JavascriptLibrary * library = scriptContext->GetLibrary();
// process function name and get property ID
JavascriptString* methodString = VarTo<JavascriptString>(args.Values[1]);
PropertyRecord* methodPropertyRecord = nullptr;
methodString->GetPropertyRecord((PropertyRecord const **) &methodPropertyRecord, false);
PropertyId methodPropID = methodPropertyRecord->GetPropertyId();
DynamicObject *installTarget = nullptr;
bool isStatic = false;
PropertyString *classPropString = nullptr;
JavascriptString *fullName = nullptr;
JavascriptString *dot = library->GetDotString();
JsBuiltInFile current = (static_cast<JsBuiltInEngineInterfaceExtensionObject*>(scriptContext->GetLibrary()
->GetEngineInterfaceObject()->GetEngineExtension(EngineInterfaceExtensionKind_JsBuiltIn)))->current;
// determine what object this function is being added too
switch (current)
{
#define file(class, type, obj) \
case class##_##type: \
isStatic = static_cast<bool>(IsTypeStatic::##type); \
installTarget = library->Get##obj##(); \
classPropString = scriptContext->GetPropertyString(PropertyIds::class); \
break;
JsBuiltIns(file)
}
Assert(methodString && classPropString && installTarget && methodPropID != PropertyIds::_none);
if (isStatic)
{
fullName = JavascriptString::Concat3(classPropString, dot, methodString);
}
else
{
JavascriptString *dotPrototypeDot = JavascriptString::Concat3(dot, scriptContext->GetPropertyString(PropertyIds::prototype), dot);
fullName = JavascriptString::Concat3(classPropString, dotPrototypeDot, methodString);
}
ScriptFunction *func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(
UnsafeVarTo<ScriptFunction>(args.Values[2]),
fullName,
false /* isConstructor */,
true /* isJsBuiltIn */,
true /* isPublic */
);
library->AddMember(installTarget, methodPropID, func);
// Make function available to other internal facilities that need it
// applicable for specific functions only - this may need review upon moving other functions into JsBuiltins
if (current == JsBuiltInFile::Array_prototype)
{
switch (methodPropID)
{
case PropertyIds::entries:
library->arrayPrototypeEntriesFunction = func;
break;
case PropertyIds::values:
library->arrayPrototypeValuesFunction = func;
library->AddMember(installTarget, PropertyIds::_symbolIterator, func);
break;
case PropertyIds::keys:
library->arrayPrototypeKeysFunction = func;
break;
case PropertyIds::forEach:
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_forEach, func);
break;
case PropertyIds::filter:
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_filter, func);
break;
case PropertyIds::indexOf:
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_indexOf, func);
break;
case PropertyIds::reduce:
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInArray_prototype_reduce, func);
break;
}
}
else if (current == JsBuiltInFile::Math_object)
{
switch (methodPropID)
{
case PropertyIds::max:
library->mathMax = func;
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMath_object_max, func);
break;
case PropertyIds::min:
library->mathMin = func;
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMath_object_min, func);
break;
}
}
//Don't need to return anything
return library->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_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::ToVarIntCheck(JavascriptConversion::ToInteger(value, scriptContext), scriptContext);
}
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::IsNonES5Array(iterable));
if (VarIs<TypedArrayBase>(iterable))
{
typedArrayBase = VarTo<TypedArrayBase>(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_GetIteratorPrototype(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
Assert(callInfo.Count == 1);
return scriptContext->GetLibrary()->iteratorPrototype;
}
Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_InitInternalProperties(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
DynamicObject* obj = VarTo<DynamicObject>(args.Values[1]);
unsigned propCount = TaggedInt::ToUInt32(args.Values[2]);
Assert(callInfo.Count == 3 + propCount);
for (unsigned i = 0; i < propCount; i++)
{
JavascriptString *propName = VarTo<JavascriptString>(args.Values[i + 3]);
obj->SetPropertyWithAttributes(JavascriptOperators::GetPropertyId(propName, scriptContext), scriptContext->GetLibrary()->GetNull(), PropertyWritable, nullptr);
}
return obj;
}
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_Internal_ArrayCreateDataPropertyOrThrow(RecyclableObject *function, CallInfo callInfo, ...)
{
EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
AssertOrFailFast(args.Info.Count == 4);
RecyclableObject * obj = VarTo<RecyclableObject>(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();
}
}
#endif // ENABLE_JS_BUILTINS