JsBuiltInEngineInterfaceExtensionObject.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLibraryPch.h"
  6. #include "EngineInterfaceObject.h"
  7. #include "JsBuiltInEngineInterfaceExtensionObject.h"
  8. #include "Types/DeferredTypeHandler.h"
  9. #ifdef ENABLE_JS_BUILTINS
  10. #include "ByteCode/ByteCodeSerializer.h"
  11. #include "errstr.h"
  12. #include "ByteCode/ByteCodeDumper.h"
  13. #pragma warning(push)
  14. #pragma warning(disable:4309) // truncation of constant value
  15. #pragma warning(disable:4838) // conversion from 'int' to 'const char' requires a narrowing conversion
  16. #if DISABLE_JIT
  17. #if TARGET_64
  18. #include "JsBuiltIn/JsBuiltIn.js.nojit.bc.64b.h"
  19. #else
  20. #include "JsBuiltIn/JsBuiltIn.js.nojit.bc.32b.h"
  21. #endif // TARGET_64
  22. #else
  23. #if TARGET_64
  24. #include "JsBuiltIn/JsBuiltIn.js.bc.64b.h"
  25. #else
  26. #include "JsBuiltIn/JsBuiltIn.js.bc.32b.h"
  27. #endif // TARGET_64
  28. #endif // DISABLE_JIT
  29. #pragma warning(pop)
  30. #define IfFailAssertMsgAndThrowHr(op, msg) \
  31. if (FAILED(hr=(op))) \
  32. { \
  33. AssertMsg(false, msg); \
  34. JavascriptError::MapAndThrowError(scriptContext, hr); \
  35. } \
  36. #define FUNCTIONKIND_VALUES(VALUE) \
  37. VALUE(Array, values, Prototype) \
  38. VALUE(Array, keys, Prototype) \
  39. VALUE(Array, entries, Prototype) \
  40. VALUE(Array, indexOf, Prototype) \
  41. VALUE(Array, filter, Prototype) \
  42. VALUE(Array, flat, Prototype) \
  43. VALUE(Array, flatMap, Prototype) \
  44. VALUE(Array, forEach, Prototype) \
  45. VALUE(Array, some, Prototype) \
  46. VALUE(Array, sort, Prototype) \
  47. VALUE(Array, every, Prototype) \
  48. VALUE(Array, includes, Prototype) \
  49. VALUE(Array, reduce, Prototype) \
  50. VALUE(Object, fromEntries, Constructor) \
  51. VALUE(Math, max, Object) \
  52. VALUE(Math, min, Object)
  53. enum class FunctionKind
  54. {
  55. #define VALUE(ClassName, methodName, propertyType) ClassName##_##methodName,
  56. FUNCTIONKIND_VALUES(VALUE)
  57. #undef VALUE
  58. Max
  59. };
  60. enum class IsPropertyTypeStatic : bool
  61. {
  62. Prototype = false,
  63. Constructor = true,
  64. Object = true
  65. };
  66. namespace Js
  67. {
  68. JsBuiltInEngineInterfaceExtensionObject::JsBuiltInEngineInterfaceExtensionObject(ScriptContext * scriptContext) :
  69. EngineExtensionObjectBase(EngineInterfaceExtensionKind_JsBuiltIn, scriptContext),
  70. jsBuiltInByteCode(nullptr),
  71. wasInitialized(false)
  72. {
  73. }
  74. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterFunction));
  75. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterChakraLibraryFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction));
  76. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetLength(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetLength));
  77. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetIteratorPrototype(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetIteratorPrototype));
  78. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_InitInternalProperties(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_InitInternalProperties));
  79. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ToLengthFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToLengthFunction));
  80. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ToIntegerFunction(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToIntegerFunction));
  81. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ArraySpeciesCreate(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArraySpeciesCreate));
  82. NoProfileFunctionInfo JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow(FORCE_NO_WRITE_BARRIER_TAG(JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow));
  83. void JsBuiltInEngineInterfaceExtensionObject::Initialize()
  84. {
  85. if (wasInitialized)
  86. {
  87. return;
  88. }
  89. JavascriptLibrary* library = scriptContext->GetLibrary();
  90. DynamicObject* commonObject = library->GetEngineInterfaceObject()->GetCommonNativeInterfaces();
  91. if (scriptContext->IsJsBuiltInEnabled())
  92. {
  93. Assert(library->GetEngineInterfaceObject() != nullptr);
  94. builtInNativeInterfaces = DynamicObject::New(library->GetRecycler(),
  95. DynamicType::New(scriptContext, TypeIds_Object, commonObject, nullptr,
  96. DeferredTypeHandler<InitializeJsBuiltInNativeInterfaces>::GetDefaultInstance()));
  97. library->AddMember(library->GetEngineInterfaceObject(), Js::PropertyIds::JsBuiltIn, builtInNativeInterfaces);
  98. }
  99. wasInitialized = true;
  100. }
  101. void JsBuiltInEngineInterfaceExtensionObject::InitializePrototypes(ScriptContext * scriptContext)
  102. {
  103. JavascriptLibrary* library = scriptContext->GetLibrary();
  104. JavascriptString * methodName = JavascriptString::NewWithSz(_u("ArrayIterator"), scriptContext);
  105. auto arrayIterator = JavascriptOperators::GetProperty(library->GetChakraLib(), JavascriptOperators::GetPropertyId(methodName, scriptContext), scriptContext);
  106. library->arrayIteratorPrototype = VarTo<DynamicObject>(JavascriptOperators::GetProperty(VarTo<DynamicObject>(arrayIterator), PropertyIds::prototype, scriptContext));
  107. library->arrayIteratorPrototypeBuiltinNextFunction = VarTo<JavascriptFunction>(JavascriptOperators::GetProperty(library->arrayIteratorPrototype, PropertyIds::next, scriptContext));
  108. }
  109. void JsBuiltInEngineInterfaceExtensionObject::InjectJsBuiltInLibraryCode(ScriptContext * scriptContext)
  110. {
  111. JavascriptExceptionObject *pExceptionObject = nullptr;
  112. if (jsBuiltInByteCode != nullptr)
  113. {
  114. return;
  115. }
  116. try {
  117. EnsureJsBuiltInByteCode(scriptContext);
  118. Assert(jsBuiltInByteCode != nullptr);
  119. Js::ScriptFunction *functionGlobal = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode);
  120. // If we are in the debugger and doing a GetProperty of arguments, then Js Builtins code will be injected on-demand
  121. // Since it is a cross site call, we marshall not only functionGlobal but also its entire prototype chain
  122. // The prototype of functionGlobal will be shared by a normal Js function,
  123. // so marshalling will inadvertantly transition the entrypoint of the prototype to a crosssite entrypoint
  124. // So we set the prototype to null here
  125. functionGlobal->SetPrototype(scriptContext->GetLibrary()->nullValue);
  126. #ifdef ENABLE_SCRIPT_PROFILING
  127. // If we are profiling, we need to register the script to the profiler callback, so the script compiled event will be sent.
  128. if (scriptContext->IsProfiling())
  129. {
  130. scriptContext->RegisterScript(functionGlobal->GetFunctionProxy());
  131. }
  132. #endif
  133. #ifdef ENABLE_SCRIPT_DEBUGGING
  134. // Mark we are profiling library code already, so that any initialization library code called here won't be reported to profiler.
  135. // Also tell the debugger not to record events during intialization so that we don't leak information about initialization.
  136. AutoInitLibraryCodeScope autoInitLibraryCodeScope(scriptContext);
  137. #endif
  138. Js::Var args[] = { scriptContext->GetLibrary()->GetUndefined(), scriptContext->GetLibrary()->GetEngineInterfaceObject() };
  139. Js::CallInfo callInfo(Js::CallFlags_Value, _countof(args));
  140. #if ENABLE_JS_REENTRANCY_CHECK
  141. // Create a Reentrancy lock to make sure we correctly restore the lock at the end of BuiltIns initialization
  142. JsReentLock lock(scriptContext->GetThreadContext());
  143. // Clear ReentrancyLock bit as initialization code doesn't have any side effect
  144. scriptContext->GetThreadContext()->SetNoJsReentrancy(false);
  145. #endif
  146. // Clear disable implicit call bit as initialization code doesn't have any side effect
  147. {
  148. ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
  149. scriptContext->GetThreadContext()->ClearDisableImplicitFlags();
  150. JavascriptFunction::CallRootFunctionInScript(functionGlobal, Js::Arguments(callInfo, args));
  151. }
  152. Js::ScriptFunction *functionBuiltins = scriptContext->GetLibrary()->CreateScriptFunction(jsBuiltInByteCode->GetNestedFunctionForExecution(0));
  153. functionBuiltins->SetPrototype(scriptContext->GetLibrary()->nullValue);
  154. // Clear disable implicit call bit as initialization code doesn't have any side effect
  155. {
  156. ThreadContext::AutoRestoreImplicitFlags autoRestoreImplicitFlags(scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetImplicitCallFlags(), scriptContext->GetThreadContext()->GetDisableImplicitFlags());
  157. scriptContext->GetThreadContext()->ClearDisableImplicitFlags();
  158. JavascriptFunction::CallRootFunctionInScript(functionBuiltins, Js::Arguments(callInfo, args));
  159. }
  160. InitializePrototypes(scriptContext);
  161. #if DBG_DUMP
  162. if (PHASE_DUMP(Js::ByteCodePhase, functionGlobal->GetFunctionProxy()) && Js::Configuration::Global.flags.Verbose)
  163. {
  164. DumpByteCode();
  165. }
  166. #endif
  167. }
  168. catch (const JavascriptException& err)
  169. {
  170. pExceptionObject = err.GetAndClear();
  171. }
  172. if (pExceptionObject)
  173. {
  174. jsBuiltInByteCode = nullptr;
  175. if (pExceptionObject == ThreadContext::GetContextForCurrentThread()->GetPendingSOErrorObject())
  176. {
  177. JavascriptExceptionOperators::DoThrowCheckClone(pExceptionObject, scriptContext);
  178. }
  179. Js::Throw::FatalJsBuiltInError();
  180. }
  181. }
  182. bool JsBuiltInEngineInterfaceExtensionObject::InitializeJsBuiltInNativeInterfaces(DynamicObject * builtInNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
  183. {
  184. int initSlotCapacity = 6; // for register{ChakraLibrary}Function, FunctionKind, POSITIVE_INFINITY, NEGATIVE_INFINITY, and GetIteratorPrototype
  185. typeHandler->Convert(builtInNativeInterfaces, mode, initSlotCapacity);
  186. ScriptContext* scriptContext = builtInNativeInterfaces->GetScriptContext();
  187. JavascriptLibrary* library = scriptContext->GetLibrary();
  188. DynamicObject * functionKindObj = library->CreateObject();
  189. #define VALUE(ClassName, methodName, propertyType) library->AddMember(functionKindObj, PropertyIds::ClassName##_##methodName, JavascriptNumber::ToVar((int)FunctionKind::ClassName##_##methodName, scriptContext));
  190. FUNCTIONKIND_VALUES(VALUE)
  191. #undef VALUE
  192. library->AddMember(builtInNativeInterfaces, PropertyIds::FunctionKind, functionKindObj);
  193. library->AddMember(builtInNativeInterfaces, PropertyIds::POSITIVE_INFINITY, library->GetPositiveInfinite());
  194. library->AddMember(builtInNativeInterfaces, PropertyIds::NEGATIVE_INFINITY, library->GetNegativeInfinite());
  195. library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerChakraLibraryFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterChakraLibraryFunction, 2);
  196. library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterFunction, 2);
  197. library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::GetIteratorPrototype, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_Internal_GetIteratorPrototype, 1);
  198. builtInNativeInterfaces->SetHasNoEnumerableProperties(true);
  199. return true;
  200. }
  201. #if DBG
  202. void JsBuiltInEngineInterfaceExtensionObject::DumpByteCode()
  203. {
  204. Output::Print(_u("Dumping JS Built Ins Byte Code:\n"));
  205. Assert(this->jsBuiltInByteCode);
  206. Js::ByteCodeDumper::DumpRecursively(jsBuiltInByteCode);
  207. }
  208. #endif // DBG
  209. void JsBuiltInEngineInterfaceExtensionObject::EnsureJsBuiltInByteCode(ScriptContext * scriptContext)
  210. {
  211. if (jsBuiltInByteCode == nullptr)
  212. {
  213. SourceContextInfo* sourceContextInfo = RecyclerNewStructZ(scriptContext->GetRecycler(), SourceContextInfo);
  214. sourceContextInfo->dwHostSourceContext = Js::Constants::JsBuiltInSourceContext;
  215. sourceContextInfo->isHostDynamicDocument = true;
  216. sourceContextInfo->sourceContextId = Js::Constants::JsBuiltInSourceContextId;
  217. Assert(sourceContextInfo != nullptr);
  218. SRCINFO si;
  219. memset(&si, 0, sizeof(si));
  220. si.sourceContextInfo = sourceContextInfo;
  221. SRCINFO *hsi = scriptContext->AddHostSrcInfo(&si);
  222. uint32 flags = fscrJsBuiltIn | (CONFIG_FLAG(CreateFunctionProxy) && !scriptContext->IsProfiling() ? fscrAllowFunctionProxy : 0);
  223. HRESULT hr = Js::ByteCodeSerializer::DeserializeFromBuffer(scriptContext, flags, (LPCUTF8)nullptr, hsi, (byte*)Library_Bytecode_JsBuiltIn, nullptr, &jsBuiltInByteCode);
  224. IfFailAssertMsgAndThrowHr(hr, "Failed to deserialize JsBuiltIn.js bytecode - very probably the bytecode needs to be rebuilt.");
  225. this->SetHasBytecode();
  226. }
  227. }
  228. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...)
  229. {
  230. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  231. AssertOrFailFast(args.Info.Count >= 3 && VarIs<JavascriptString>(args.Values[1]) && VarIs<ScriptFunction>(args.Values[2]));
  232. JavascriptLibrary * library = scriptContext->GetLibrary();
  233. JavascriptString* methodName = UnsafeVarTo<JavascriptString>(args.Values[1]);
  234. // chakra library functions, since they aren't public, can be constructors (__chakraLibrary.ArrayIterator is one)
  235. ScriptFunction* func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(
  236. UnsafeVarTo<ScriptFunction>(args.Values[2]),
  237. methodName,
  238. true /* isConstructor */,
  239. true /* isJsBuiltIn */,
  240. false /* isPublic */
  241. );
  242. PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext);
  243. library->AddMember(library->GetChakraLib(), functionIdentifier, func);
  244. //Don't need to return anything
  245. return library->GetUndefined();
  246. }
  247. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterFunction(RecyclableObject* function, CallInfo callInfo, ...)
  248. {
  249. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  250. AssertOrFailFast(args.Info.Count == 3 && TaggedInt::Is(args.Values[1]) && VarIs<ScriptFunction>(args.Values[2]));
  251. JavascriptLibrary * library = scriptContext->GetLibrary();
  252. FunctionKind funcKind = static_cast<FunctionKind>(TaggedInt::ToInt32(args.Values[1]));
  253. AssertOrFailFast(funcKind >= (FunctionKind)0 && funcKind < FunctionKind::Max);
  254. DynamicObject *installTarget = nullptr;
  255. bool isStatic = false;
  256. PropertyId methodPropID = PropertyIds::_none;
  257. PropertyString *methodPropString = nullptr;
  258. PropertyString *classPropString = nullptr;
  259. JavascriptString *fullName = nullptr;
  260. JavascriptString *dot = library->GetDotString();
  261. switch (funcKind)
  262. {
  263. #define VALUE(ClassName, methodName, propertyType) \
  264. case FunctionKind::ClassName##_##methodName: \
  265. isStatic = static_cast<bool>(IsPropertyTypeStatic::##propertyType); \
  266. installTarget = library->Get##ClassName##propertyType##(); \
  267. methodPropID = PropertyIds::methodName; \
  268. methodPropString = scriptContext->GetPropertyString(methodPropID); \
  269. classPropString = scriptContext->GetPropertyString(PropertyIds::ClassName); \
  270. break;
  271. FUNCTIONKIND_VALUES(VALUE)
  272. #undef VALUE
  273. default:
  274. AssertOrFailFastMsg(false, "funcKind should never be outside the range of projected values");
  275. }
  276. Assert(methodPropString && classPropString && installTarget && methodPropID != PropertyIds::_none);
  277. if (isStatic)
  278. {
  279. fullName = JavascriptString::Concat3(classPropString, dot, methodPropString);
  280. }
  281. else
  282. {
  283. JavascriptString *dotPrototypeDot = JavascriptString::Concat3(dot, scriptContext->GetPropertyString(PropertyIds::prototype), dot);
  284. fullName = JavascriptString::Concat3(classPropString, dotPrototypeDot, methodPropString);
  285. }
  286. ScriptFunction *func = EngineInterfaceObject::CreateLibraryCodeScriptFunction(
  287. UnsafeVarTo<ScriptFunction>(args.Values[2]),
  288. fullName,
  289. false /* isConstructor */,
  290. true /* isJsBuiltIn */,
  291. true /* isPublic */
  292. );
  293. library->AddMember(installTarget, methodPropID, func);
  294. // do extra logic here which didnt easily fit into the macro table
  295. switch (funcKind)
  296. {
  297. case FunctionKind::Array_entries:
  298. library->arrayPrototypeEntriesFunction = func;
  299. break;
  300. case FunctionKind::Array_values:
  301. library->arrayPrototypeValuesFunction = func;
  302. library->AddMember(installTarget, PropertyIds::_symbolIterator, func);
  303. break;
  304. case FunctionKind::Array_keys:
  305. library->arrayPrototypeKeysFunction = func;
  306. break;
  307. case FunctionKind::Array_forEach:
  308. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryForEach, func);
  309. break;
  310. case FunctionKind::Array_filter:
  311. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryFilter, func);
  312. break;
  313. case FunctionKind::Array_indexOf:
  314. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryIndexOf, func);
  315. break;
  316. case FunctionKind::Array_some:
  317. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntrySome, func);
  318. break;
  319. case FunctionKind::Array_every:
  320. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryEvery, func);
  321. break;
  322. case FunctionKind::Array_includes:
  323. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryIncludes, func);
  324. break;
  325. case FunctionKind::Array_reduce:
  326. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryReduce, func);
  327. break;
  328. case FunctionKind::Math_max:
  329. library->mathMax = func;
  330. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMax, func);
  331. break;
  332. case FunctionKind::Math_min:
  333. library->mathMin = func;
  334. library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMin, func);
  335. break;
  336. // FunctionKinds with no entry functions
  337. case FunctionKind::Array_sort:
  338. case FunctionKind::Array_flat:
  339. case FunctionKind::Array_flatMap:
  340. case FunctionKind::Object_fromEntries:
  341. break;
  342. default:
  343. AssertOrFailFastMsg(false, "funcKind should never be outside the range of projected values");
  344. break;
  345. }
  346. //Don't need to return anything
  347. return library->GetUndefined();
  348. }
  349. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToLengthFunction(RecyclableObject * function, CallInfo callInfo, ...)
  350. {
  351. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  352. Assert(args.Info.Count == 2);
  353. return JavascriptNumber::ToVar(JavascriptConversion::ToLength(args.Values[1], scriptContext), scriptContext);
  354. }
  355. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ToIntegerFunction(RecyclableObject * function, CallInfo callInfo, ...)
  356. {
  357. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  358. Assert(args.Info.Count == 2);
  359. Var value = args.Values[1];
  360. if (JavascriptOperators::IsUndefinedOrNull(value))
  361. {
  362. return TaggedInt::ToVarUnchecked(0);
  363. }
  364. else if (TaggedInt::Is(value))
  365. {
  366. return value;
  367. }
  368. return JavascriptNumber::ToVarIntCheck(JavascriptConversion::ToInteger(value, scriptContext), scriptContext);
  369. }
  370. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetLength(RecyclableObject *function, CallInfo callInfo, ...)
  371. {
  372. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  373. Assert(callInfo.Count == 2);
  374. int64 length;
  375. Var iterable = args.Values[1];
  376. TypedArrayBase *typedArrayBase = nullptr;
  377. Assert(!JavascriptArray::IsNonES5Array(iterable));
  378. if (VarIs<TypedArrayBase>(iterable))
  379. {
  380. typedArrayBase = VarTo<TypedArrayBase>(iterable);
  381. if (typedArrayBase->IsDetachedBuffer())
  382. {
  383. JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
  384. }
  385. length = typedArrayBase->GetLength();
  386. }
  387. else
  388. {
  389. length = JavascriptConversion::ToLength(JavascriptOperators::OP_GetLength(iterable, scriptContext), scriptContext);
  390. }
  391. return JavascriptNumber::ToVar(length, scriptContext);
  392. }
  393. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_GetIteratorPrototype(RecyclableObject *function, CallInfo callInfo, ...)
  394. {
  395. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  396. Assert(callInfo.Count == 1);
  397. return scriptContext->GetLibrary()->iteratorPrototype;
  398. }
  399. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_InitInternalProperties(RecyclableObject *function, CallInfo callInfo, ...)
  400. {
  401. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  402. DynamicObject* obj = VarTo<DynamicObject>(args.Values[1]);
  403. unsigned propCount = TaggedInt::ToUInt32(args.Values[2]);
  404. Assert(callInfo.Count == 3 + propCount);
  405. for (unsigned i = 0; i < propCount; i++)
  406. {
  407. JavascriptString *propName = VarTo<JavascriptString>(args.Values[i + 3]);
  408. obj->SetPropertyWithAttributes(JavascriptOperators::GetPropertyId(propName, scriptContext), scriptContext->GetLibrary()->GetNull(), PropertyWritable, nullptr);
  409. }
  410. return obj;
  411. }
  412. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArraySpeciesCreate(RecyclableObject *function, CallInfo callInfo, ...)
  413. {
  414. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  415. AssertOrFailFast(args.Info.Count == 3);
  416. int64 length64 = JavascriptConversion::ToLength(args.Values[2], scriptContext);
  417. if (length64 > UINT_MAX)
  418. {
  419. JavascriptError::ThrowRangeError(scriptContext, JSERR_ArrayLengthConstructIncorrect);
  420. }
  421. uint32 length = static_cast<uint32>(length64);
  422. bool isBuiltinArrayCtor = true;
  423. RecyclableObject * newObj = JavascriptArray::ArraySpeciesCreate(args.Values[1], length, scriptContext, nullptr, nullptr, &isBuiltinArrayCtor);
  424. nullptr;
  425. if (newObj == nullptr)
  426. {
  427. newObj = scriptContext->GetLibrary()->CreateArray(length);
  428. }
  429. else
  430. {
  431. #if ENABLE_COPYONACCESS_ARRAY
  432. JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
  433. #endif
  434. }
  435. return newObj;
  436. }
  437. Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_Internal_ArrayCreateDataPropertyOrThrow(RecyclableObject *function, CallInfo callInfo, ...)
  438. {
  439. EngineInterfaceObject_CommonFunctionProlog(function, callInfo);
  440. AssertOrFailFast(args.Info.Count == 4);
  441. RecyclableObject * obj = VarTo<RecyclableObject>(args.Values[1]);
  442. double index = JavascriptConversion::ToInteger(args.Values[2], scriptContext);
  443. AssertOrFailFast(index >= 0);
  444. JavascriptArray::BigIndex bigIndex(static_cast<uint64>(index));
  445. Var item = args.Values[3];
  446. JavascriptArray::CreateDataPropertyOrThrow(obj, bigIndex, item, scriptContext);
  447. return scriptContext->GetLibrary()->GetTrue();
  448. }
  449. }
  450. #endif // ENABLE_JS_BUILTINS