lib/VM/JSLib/GlobalObject.cpp (510 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ //===----------------------------------------------------------------------===// /// \file /// Initialize the global object ES5.1 15.1 //===----------------------------------------------------------------------===// #include "hermes/Platform/Intl/PlatformIntl.h" #include "hermes/VM/JSArrayBuffer.h" #include "hermes/VM/JSDataView.h" #include "hermes/VM/JSLib.h" #include "hermes/VM/JSTypedArray.h" #include "hermes/VM/Operations.h" #include "hermes/VM/PrimitiveBox.h" #include "hermes/VM/PropertyAccessor.h" #include "hermes/VM/StringView.h" #include "dtoa/dtoa.h" #include "JSLibInternal.h" namespace hermes { namespace vm { /// ES5.1 15.1.2.4 CallResult<HermesValue> isNaN(void *, Runtime &runtime, NativeArgs args) { auto res = toNumber_RJS(runtime, args.getArgHandle(0)); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } return HermesValue::encodeBoolValue(std::isnan(res->getNumber())); } /// ES5.1 15.1.2.5 CallResult<HermesValue> isFinite(void *, Runtime &runtime, NativeArgs args) { auto res = toNumber_RJS(runtime, args.getArgHandle(0)); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } auto value = res->getDouble(); return HermesValue::encodeBoolValue(std::isfinite(value)); } /// Needed to construct Function.prototype. CallResult<HermesValue> emptyFunction(void *, Runtime &, NativeArgs) { return HermesValue::encodeUndefinedValue(); } /// Given a character \p c in radix \p radix, checks if it's valid. static bool isValidRadixChar(char16_t c, int radix) { // c is 0..9. if (c >= '0' && c <= '9') { return (radix >= 10 || c < '0' + radix); } c = letterToLower(c); return (radix > 10 && c >= 'a' && c < 'a' + radix - 10); } /// ES5.1 15.1.2.2 parseInt(string, radix) CallResult<HermesValue> parseInt(void *, Runtime &runtime, NativeArgs args) { // toString(arg0). auto strRes = toString_RJS(runtime, args.getArgHandle(0)); if (LLVM_UNLIKELY(strRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } auto str = runtime.makeHandle(std::move(*strRes)); int radix = 10; bool stripPrefix = true; // If radix (arg1) is present and not undefined, toInt32_RJS(arg1). if (args.getArgCount() > 1 && !args.getArg(1).isUndefined()) { auto intRes = toInt32_RJS(runtime, args.getArgHandle(1)); if (LLVM_UNLIKELY(intRes == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } radix = static_cast<int>(intRes->getNumber()); if (radix == 0) { radix = 10; } else if (radix < 2 || radix > 36) { return HermesValue::encodeNaNValue(); } else if (radix != 16) { stripPrefix = false; } } auto strView = StringPrimitive::createStringView(runtime, str); auto begin = strView.begin(); auto end = strView.end(); // Remove leading whitespaces. while (begin != end && (isWhiteSpaceChar(*begin) || isLineTerminatorChar(*begin))) { ++begin; } // Process sign. int sign = 1; if (begin != end && (*begin == u'+' || *begin == u'-')) { if (*begin == u'-') { sign = -1; } ++begin; } // Strip 0x or 0X for 16-radix number. if (stripPrefix && begin != end) { if (*begin == u'0') { ++begin; if (begin != end && letterToLower(*begin) == u'x') { ++begin; radix = 16; } else { --begin; } } } // Find the longest prefix that's still a valid int. auto realEnd = begin; for (; realEnd != end && isValidRadixChar(*realEnd, radix); ++realEnd) { } if (realEnd == begin) { // Return NaN if string has no digits. return HermesValue::encodeNaNValue(); } return HermesValue::encodeDoubleValue( sign * parseIntWithRadix(strView.slice(begin, realEnd), radix)); } // Check if str1 is a prefix of str2. static bool isPrefix(StringView str1, StringView str2) { if (str1.length() > str2.length()) { return false; } for (auto first1 = str1.begin(), last1 = str1.end(), first2 = str2.begin(); first1 != last1; ++first1, ++first2) { if (*first1 != *first2) { return false; } } return true; } /// ES5.1 15.1.2.3 parseFloat(string) CallResult<HermesValue> parseFloat(void *, Runtime &runtime, NativeArgs args) { // toString(arg0). auto res = toString_RJS(runtime, args.getArgHandle(0)); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { return ExecutionStatus::EXCEPTION; } auto strHandle = runtime.makeHandle(std::move(*res)); auto origStr = StringPrimitive::createStringView(runtime, strHandle); auto &idTable = runtime.getIdentifierTable(); // Trim leading whitespaces. auto begin = origStr.begin(); auto end = origStr.end(); while (begin != end && (isWhiteSpaceChar(*begin) || isLineTerminatorChar(*begin))) { ++begin; } StringView str16 = origStr.slice(begin, end); // Check for special values. // parseFloat allows for partial match, hence we have to check for // substring. if (LLVM_UNLIKELY(isPrefix( idTable.getStringView( runtime, Predefined::getSymbolID(Predefined::Infinity)), str16))) { return HermesValue::encodeDoubleValue( std::numeric_limits<double>::infinity()); } if (LLVM_UNLIKELY(isPrefix( idTable.getStringView( runtime, Predefined::getSymbolID(Predefined::PositiveInfinity)), str16))) { return HermesValue::encodeDoubleValue( std::numeric_limits<double>::infinity()); } if (LLVM_UNLIKELY(isPrefix( idTable.getStringView( runtime, Predefined::getSymbolID(Predefined::NegativeInfinity)), str16))) { return HermesValue::encodeDoubleValue( -std::numeric_limits<double>::infinity()); } if (LLVM_UNLIKELY(isPrefix( idTable.getStringView( runtime, Predefined::getSymbolID(Predefined::NaN)), str16))) { return HermesValue::encodeNaNValue(); } // Copy 16 bit chars into 8 bit chars as long as the character is // still a valid decimal number character. auto len = str16.length(); llvh::SmallVector<char, 32> str8(len + 1); uint32_t i = 0; for (auto c : str16) { if ((c >= u'0' && c <= u'9') || c == '.' || letterToLower(c) == 'e' || c == '+' || c == '-') { str8[i] = static_cast<char>(c); } else { break; } ++i; } if (i == 0) { // Empty string. return HermesValue::encodeNaNValue(); } // Use hermes_g_strtod to figure out the longest prefix that's still valid. // hermes_g_strtod will try to convert the string to int for as long as it // can, and set endPtr to the last location where the prefix so far is still // a valid integer. len = i; str8[len] = '\0'; char *endPtr; ::hermes_g_strtod(str8.data(), &endPtr); if (endPtr == str8.data()) { // Empty string. return HermesValue::encodeNaNValue(); } // Now we know the prefix untill endPtr is a valid int. *endPtr = '\0'; return HermesValue::encodeDoubleValue( ::hermes_g_strtod(str8.data(), &endPtr)); } /// Customized global function. gc() forces a GC collect. CallResult<HermesValue> gc(void *, Runtime &runtime, NativeArgs) { runtime.collect("forced"); return HermesValue::encodeUndefinedValue(); } CallResult<HermesValue> throwTypeError(void *ctx, Runtime &runtime, NativeArgs) { static const char *TypeErrorMessage[] = { "Restricted in strict mode", "Dynamic requires are not allowed after static resolution", }; uint64_t kind = (uint64_t)ctx; assert( kind < (uint64_t)TypeErrorKind::NumKinds && "[[ThrowTypeError]] wrong error kind passed as context"); return runtime.raiseTypeError(TypeErrorMessage[kind]); } // NOTE: when declaring more global symbols, don't forget to update // "Libhermes.h". void initGlobalObject(Runtime &runtime, const JSLibFlags &jsLibFlags) { GCScope gcScope{runtime, "initGlobalObject", 310}; // Not enumerable, not writable, not configurable. DefinePropertyFlags constantDPF = DefinePropertyFlags::getDefaultNewPropertyFlags(); constantDPF.enumerable = 0; constantDPF.writable = 0; constantDPF.configurable = 0; // Not enumerable, but writable and configurable. DefinePropertyFlags normalDPF = DefinePropertyFlags::getNewNonEnumerableFlags(); // Not enumerable, not writable but configurable. DefinePropertyFlags configurableOnlyPDF = DefinePropertyFlags::getDefaultNewPropertyFlags(); configurableOnlyPDF.enumerable = 0; configurableOnlyPDF.writable = 0; /// Clear the configurable flag. DefinePropertyFlags clearConfigurableDPF{}; clearConfigurableDPF.setConfigurable = 1; clearConfigurableDPF.configurable = 0; // Define a function on the global object with name \p name. // Allocates a NativeObject and puts it in the global object. auto defineGlobalFunc = [&](SymbolID name, NativeFunctionPtr functionPtr, unsigned paramCount) { gcScope.clearAllHandles(); auto func = NativeFunction::createWithoutPrototype( runtime, nullptr, functionPtr, name, paramCount); runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, name, normalDPF, func)); return func; }; // 15.1.1.1 NaN. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::NaN), constantDPF, runtime.makeHandle(HermesValue::encodeNaNValue()))); // 15.1.1.2 Infinity. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::Infinity), constantDPF, runtime.makeHandle(HermesValue::encodeDoubleValue( std::numeric_limits<double>::infinity())))); // 15.1.1.2 undefined. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::undefined), constantDPF, runtime.makeHandle(HermesValue::encodeUndefinedValue()))); // "Forward declaration" of Object.prototype. Its properties will be populated // later. runtime.objectPrototype = JSObject::create(runtime, Runtime::makeNullHandle<JSObject>()) .getHermesValue(); runtime.objectPrototypeRawPtr = vmcast<JSObject>(runtime.objectPrototype); // "Forward declaration" of Error.prototype. Its properties will be populated // later. runtime.ErrorPrototype = JSObject::create(runtime).getHermesValue(); // "Forward declaration" of the prototype for native error types. Their // properties will be populated later. #define NATIVE_ERROR_TYPE(name) \ runtime.name##Prototype = \ JSObject::create( \ runtime, Handle<JSObject>::vmcast(&runtime.ErrorPrototype)) \ .getHermesValue(); #include "hermes/VM/NativeErrorTypes.def" // "Forward declaration" of the internal CallSite prototype. Its properties // will be populated later. runtime.callSitePrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of Function.prototype. Its properties will be // populated later. Handle<NativeFunction> funcRes = NativeFunction::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype), nullptr, emptyFunction, Predefined::getSymbolID(Predefined::emptyString), 0, Runtime::makeNullHandle<JSObject>()); runtime.functionPrototype = funcRes.getHermesValue(); runtime.functionPrototypeRawPtr = funcRes.get(); runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( Handle<JSObject>::vmcast(&runtime.functionPrototype), runtime, Predefined::getSymbolID(Predefined::length), configurableOnlyPDF, Runtime::getZeroValue())); // [[ThrowTypeError]]. auto throwTypeErrorFunction = NativeFunction::create( runtime, Handle<JSObject>::vmcast(&runtime.functionPrototype), (void *)TypeErrorKind::NonStrictOnly, throwTypeError, Predefined::getSymbolID(Predefined::emptyString), 0, Runtime::makeNullHandle<JSObject>()); runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( throwTypeErrorFunction, runtime, Predefined::getSymbolID(Predefined::length), clearConfigurableDPF, Runtime::getUndefinedValue())); runtime.throwTypeErrorAccessor = runtime.ignoreAllocationFailure(PropertyAccessor::create( runtime, throwTypeErrorFunction, throwTypeErrorFunction)); // Define the 'parseInt' function. runtime.parseIntFunction = defineGlobalFunc( Predefined::getSymbolID(Predefined::parseInt), parseInt, 2) .getHermesValue(); // Define the 'parseFloat' function. runtime.parseFloatFunction = defineGlobalFunc( Predefined::getSymbolID(Predefined::parseFloat), parseFloat, 1) .getHermesValue(); // "Forward declaration" of String.prototype. Its properties will be // populated later. runtime.stringPrototype = runtime .ignoreAllocationFailure(JSString::create( runtime, runtime.getPredefinedStringHandle(Predefined::emptyString), Handle<JSObject>::vmcast(&runtime.objectPrototype))) .getHermesValue(); // "Forward declaration" of Number.prototype. Its properties will be // populated later. runtime.numberPrototype = JSNumber::create( runtime, +0.0, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of Boolean.prototype. Its properties will be // populated later. runtime.booleanPrototype = JSBoolean::create( runtime, false, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of Symbol.prototype. Its properties will be // populated later. runtime.symbolPrototype = JSObject::create(runtime).getHermesValue(); // "Forward declaration" of Date.prototype. Its properties will be // populated later. runtime.datePrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of %IteratorPrototype%. runtime.iteratorPrototype = JSObject::create(runtime).getHermesValue(); // "Forward declaration" of Array.prototype. Its properties will be // populated later. runtime.arrayPrototype = runtime .ignoreAllocationFailure(JSArray::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype), JSArray::createClass( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)), 0, 0)) .getHermesValue(); // Declare the array class. runtime.arrayClass = JSArray::createClass( runtime, Handle<JSObject>::vmcast(&runtime.arrayPrototype)) .getHermesValue(); // "Forward declaration" of ArrayBuffer.prototype. Its properties will be // populated later. runtime.arrayBufferPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of DataView.prototype. Its properties will be // populated later. runtime.dataViewPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of TypedArrayBase.prototype. Its properties will be // populated later. runtime.typedArrayBasePrototype = JSObject::create(runtime).getHermesValue(); // Typed arrays // NOTE: a TypedArray's prototype is a normal object, not a TypedArray. #define TYPED_ARRAY(name, type) \ runtime.name##ArrayPrototype = \ JSObject::create( \ runtime, Handle<JSObject>::vmcast(&runtime.typedArrayBasePrototype)) \ .getHermesValue(); #include "hermes/VM/TypedArrays.def" // "Forward declaration" of Set.prototype. Its properties will be // populated later. runtime.setPrototype = JSObject::create(runtime).getHermesValue(); runtime.setIteratorPrototype = createSetIteratorPrototype(runtime).getHermesValue(); // "Forward declaration" of Map.prototype. Its properties will be // populated later. runtime.mapPrototype = JSObject::create(runtime).getHermesValue(); runtime.mapIteratorPrototype = createMapIteratorPrototype(runtime).getHermesValue(); // "Forward declaration" of RegExp.prototype. // ES6: 21.2.5 "The RegExp prototype object is an ordinary object. It is not a // RegExp instance..." runtime.regExpPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.objectPrototype)) .getHermesValue(); // "Forward declaration" of WeakMap.prototype. runtime.weakMapPrototype = JSObject::create(runtime).getHermesValue(); // "Forward declaration" of WeakSet.prototype. runtime.weakSetPrototype = JSObject::create(runtime).getHermesValue(); // "Forward declaration" of %ArrayIteratorPrototype%. runtime.arrayIteratorPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.iteratorPrototype)) .getHermesValue(); // "Forward declaration" of %StringIteratorPrototype%. runtime.stringIteratorPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.iteratorPrototype)) .getHermesValue(); // "Forward declaration" of %RegExpStringIteratorPrototype%. runtime.regExpStringIteratorPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.iteratorPrototype)) .getHermesValue(); // "Forward declaration" of "Generator prototype object" runtime.generatorPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.iteratorPrototype)) .getHermesValue(); // "Forward declaration" of %GeneratorFunction.prototype% runtime.generatorFunctionPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.functionPrototype)) .getHermesValue(); // "Forward declaration" of %AsyncFunction.prototype% runtime.asyncFunctionPrototype = JSObject::create( runtime, Handle<JSObject>::vmcast(&runtime.functionPrototype)) .getHermesValue(); // Object constructor. createObjectConstructor(runtime); // JSError constructor. runtime.errorConstructor = createErrorConstructor(runtime).getHermesValue(); // All Native Error constructors. #define NATIVE_ERROR_TYPE(name) \ create##name##Constructor(runtime); \ gcScope.clearAllHandles(); #include "hermes/VM/NativeErrorTypes.def" // Populate the internal CallSite prototype. populateCallSitePrototype(runtime); // String constructor. createStringConstructor(runtime); // Function constructor. runtime.functionConstructor = createFunctionConstructor(runtime).getHermesValue(); // Number constructor. createNumberConstructor(runtime); // Boolean constructor. createBooleanConstructor(runtime); // Date constructor. createDateConstructor(runtime); // RegExp constructor createRegExpConstructor(runtime); runtime.regExpLastInput = HermesValue::encodeUndefinedValue(); runtime.regExpLastRegExp = HermesValue::encodeUndefinedValue(); // Array constructor. createArrayConstructor(runtime); // ArrayBuffer constructor. createArrayBufferConstructor(runtime); // DataView constructor. createDataViewConstructor(runtime); // TypedArrayBase constructor. runtime.typedArrayBaseConstructor = createTypedArrayBaseConstructor(runtime).getHermesValue(); #define TYPED_ARRAY(name, type) \ runtime.name##ArrayConstructor = \ create##name##ArrayConstructor(runtime).getHermesValue(); \ gcScope.clearAllHandles(); #include "hermes/VM/TypedArrays.def" // Set constructor. createSetConstructor(runtime); // Map constructor. createMapConstructor(runtime); // WeakMap constructor. createWeakMapConstructor(runtime); // WeakSet constructor. createWeakSetConstructor(runtime); // Symbol constructor. createSymbolConstructor(runtime); /// %IteratorPrototype%. populateIteratorPrototype(runtime); /// Array Iterator. populateArrayIteratorPrototype(runtime); /// String Iterator. populateStringIteratorPrototype(runtime); /// RegExp String Iterator. populateRegExpStringIteratorPrototype(runtime); // GeneratorFunction constructor (not directly exposed in the global object). createGeneratorFunctionConstructor(runtime); // AsyncFunction constructor (not directly exposed in the global object). createAsyncFunctionConstructor(runtime); // %GeneratorPrototype%. populateGeneratorPrototype(runtime); // Proxy constructor. if (LLVM_UNLIKELY(runtime.hasES6Proxy())) { createProxyConstructor(runtime); } // Define the global Math object runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::Math), normalDPF, createMathObject(runtime))); // Define the global JSON object runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::JSON), normalDPF, createJSONObject(runtime))); if (LLVM_UNLIKELY(runtime.hasES6Proxy())) { // Define the global Reflect object runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::Reflect), normalDPF, createReflectObject(runtime))); } // Define the global %HermesInternal object. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::HermesInternal), constantDPF, createHermesInternalObject(runtime, jsLibFlags))); #ifdef HERMES_ENABLE_DEBUGGER // Define the global %DebuggerInternal object. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, runtime.getIdentifierTable().registerLazyIdentifier( createASCIIRef("DebuggerInternal")), constantDPF, createDebuggerInternalObject(runtime))); #endif // HERMES_ENABLE_DEBUGGER // Define the 'print' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::print), print, 1); // Define the 'eval' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::eval), eval, 1); // Define the 'isNaN' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::isNaN), isNaN, 1); // Define the 'isFinite' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::isFinite), isFinite, 1); // Define the 'escape' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::escape), escape, 1); // Define the 'unescape' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::unescape), unescape, 1); // Define the 'decodeURI' function. defineGlobalFunc( Predefined::getSymbolID(Predefined::decodeURI), decodeURI, 1); // Define the 'decodeURIComponent' function. defineGlobalFunc( Predefined::getSymbolID(Predefined::decodeURIComponent), decodeURIComponent, 1); // Define the 'encodeURI' function. defineGlobalFunc( Predefined::getSymbolID(Predefined::encodeURI), encodeURI, 1); // Define the 'encodeURIComponent' function. defineGlobalFunc( Predefined::getSymbolID(Predefined::encodeURIComponent), encodeURIComponent, 1); // Define the 'globalThis' property. runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::globalThis), normalDPF, runtime.getGlobal())); // Define the 'require' function. runtime.requireFunction = NativeFunction::create( runtime, Handle<JSObject>::vmcast(&runtime.functionPrototype), nullptr, require, Predefined::getSymbolID(Predefined::require), 1, Runtime::makeNullHandle<JSObject>()) .getHermesValue(); // Define the 'gc' function. defineGlobalFunc(Predefined::getSymbolID(Predefined::gc), gc, 0); #ifdef HERMES_ENABLE_IR_INSTRUMENTATION // Define the global __instrument object runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, runtime.getIdentifierTable().registerLazyIdentifier( createASCIIRef("__instrument")), normalDPF, createInstrumentObject(runtime))); #endif #ifdef HERMES_ENABLE_INTL // Define the global Intl object // TODO T65916424: Consider how we can move this somewhere more modular. if (LLVM_UNLIKELY(runtime.hasIntl())) { runtime.ignoreAllocationFailure(JSObject::defineOwnProperty( runtime.getGlobal(), runtime, Predefined::getSymbolID(Predefined::Intl), normalDPF, intl::createIntlObject(runtime))); } #endif } } // namespace vm } // namespace hermes