LWNode_Release_210902_60ce3db 36/263436/1 submit/tizen/20210902.074719
authorRyan Hyun Choi <ryan.choi@samsung.com>
Thu, 2 Sep 2021 07:07:52 +0000 (16:07 +0900)
committerRyan Hyun Choi <ryan.choi@samsung.com>
Thu, 2 Sep 2021 07:08:45 +0000 (16:08 +0900)
Change-Id: Id542c05f38654454540ec38b059c18932f375cbb
Signed-off-by: Ryan Choi <ryan.choi@samsung.com>
245 files changed:
configure.py
lib/buffer.js
lib/internal/assert/calltracker.js
lib/internal/bootstrap/node.js
lib/internal/child_process.js
lib/internal/child_process_origin.js [deleted file]
lib/internal/histogram.js
lib/internal/histogram_origin.js [deleted file]
lib/internal/process/per_thread.js
lib/internal/source_map/source_map.js
lib/internal/source_map/source_map.origin.js [deleted file]
lib/internal/vm/module.js
lib/internal/vm/module.origin.js [deleted file]
lib/repl.js
lib/vm.js
lwnode/build-cctest-node.sh [new file with mode: 0755]
lwnode/build-cctest.sh
lwnode/build.sh
lwnode/code/escargotshim/common.gypi
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake [deleted file]
lwnode/code/escargotshim/deps/escargot/build/config.cmake
lwnode/code/escargotshim/deps/escargot/build/escargot.cmake
lwnode/code/escargotshim/deps/escargot/build/target.cmake [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/Escargot.h
lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.cpp
lwnode/code/escargotshim/deps/escargot/src/api/EscargotPublic.h
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFromSyncIterator.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinPromise.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/codecache/CodeCacheReaderWriter.cpp
lwnode/code/escargotshim/deps/escargot/src/interpreter/ByteCodeInterpreter.cpp
lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/Intl.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/parser/Script.cpp
lwnode/code/escargotshim/deps/escargot/src/parser/esprima_cpp/esprima.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBufferObject.h
lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayObject.h
lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/BackingStore.h
lwnode/code/escargotshim/deps/escargot/src/runtime/BigInt.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/Context.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/DataViewObject.h
lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/FunctionTemplate.h
lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinPromise.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.h [deleted file]
lwnode/code/escargotshim/deps/escargot/src/runtime/Object.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/Object.h
lwnode/code/escargotshim/deps/escargot/src/runtime/ObjectTemplate.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/Platform.h
lwnode/code/escargotshim/deps/escargot/src/runtime/PointerValue.h
lwnode/code/escargotshim/deps/escargot/src/runtime/RegExpObject.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/SharedArrayBufferObject.h
lwnode/code/escargotshim/deps/escargot/src/runtime/Template.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/Template.h
lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/TypedArrayObject.h
lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.cpp
lwnode/code/escargotshim/deps/escargot/src/runtime/VMInstance.h
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/shell/Shell.cpp
lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h [new file with mode: 0644]
lwnode/code/escargotshim/deps/escargot/src/wasm/GlobalObjectBuiltinWASM.cpp
lwnode/code/escargotshim/deps/escargot/src/wasm/WASMOperations.cpp
lwnode/code/escargotshim/deps/escargot/third_party/wasm/CMakeLists.txt
lwnode/code/escargotshim/escargot.gyp
lwnode/code/escargotshim/escargotshim.gyp
lwnode/code/escargotshim/include/lwnode-internal.h
lwnode/code/escargotshim/include/lwnode/lwnode.h [new file with mode: 0644]
lwnode/code/escargotshim/include/v8.h
lwnode/code/escargotshim/lib/stack_frame.js [deleted file]
lwnode/code/escargotshim/src/api-data.cc
lwnode/code/escargotshim/src/api-environment.cc
lwnode/code/escargotshim/src/api-exception.cc
lwnode/code/escargotshim/src/api-scripts.cc
lwnode/code/escargotshim/src/api-serialization.cc
lwnode/code/escargotshim/src/api-template.cc
lwnode/code/escargotshim/src/api.h
lwnode/code/escargotshim/src/api/context.cc
lwnode/code/escargotshim/src/api/context.h
lwnode/code/escargotshim/src/api/engine.cc
lwnode/code/escargotshim/src/api/es-helper.cc
lwnode/code/escargotshim/src/api/es-helper.h
lwnode/code/escargotshim/src/api/es-v8-helper.cc
lwnode/code/escargotshim/src/api/es-v8-helper.h
lwnode/code/escargotshim/src/api/extra-data.cc
lwnode/code/escargotshim/src/api/extra-data.h
lwnode/code/escargotshim/src/api/function.cc
lwnode/code/escargotshim/src/api/function.h
lwnode/code/escargotshim/src/api/handle.cc
lwnode/code/escargotshim/src/api/handle.h
lwnode/code/escargotshim/src/api/isolate.cc
lwnode/code/escargotshim/src/api/isolate.h
lwnode/code/escargotshim/src/api/object.cc
lwnode/code/escargotshim/src/api/serializer.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/api/serializer.h [new file with mode: 0644]
lwnode/code/escargotshim/src/api/stack-trace.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/api/stack-trace.h [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils.h
lwnode/code/escargotshim/src/api/utils/debug.cc
lwnode/code/escargotshim/src/api/utils/flags.cc [deleted file]
lwnode/code/escargotshim/src/api/utils/flags.h [deleted file]
lwnode/code/escargotshim/src/api/utils/gc-container.h
lwnode/code/escargotshim/src/api/utils/gc.cc
lwnode/code/escargotshim/src/api/utils/gc.h
lwnode/code/escargotshim/src/api/utils/logger.cc [deleted file]
lwnode/code/escargotshim/src/api/utils/logger.h [deleted file]
lwnode/code/escargotshim/src/api/utils/logger/flags.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/logger/flags.h [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/logger/logger.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/logger/logger.h [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/logger/trace.h [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/misc.h
lwnode/code/escargotshim/src/api/utils/smaps.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/api/utils/smaps.h [new file with mode: 0644]
lwnode/code/escargotshim/src/base.h
lwnode/code/escargotshim/src/lwnode.cc [new file with mode: 0644]
lwnode/code/escargotshim/src/unimplemented.h
node.gyp
packaging/lwnode.spec
src/node.h
src/node_platform.cc
src/node_process_methods.cc
src/node_worker.cc
tools/gyp_node.py
tools/test.py

index 4e3e8d5e546b361dbe617209d020d25d5daf6569..20a451df0bfc9114141264a72877dc1ddc85ccdf 100755 (executable)
@@ -88,9 +88,9 @@ lwnode_optgroup.add_option('--tizen',
     help='Platform: tizen')
 
 lwnode_optgroup.add_option('--profile',
-    choices=['none', 'tv', 'kiosk'],
-    default='none',
-    help='Build profile: none | tv | kiosk')
+    choices=['common', 'tv', 'kiosk'],
+    default='common',
+    help='Build profile: common | tv | kiosk')
 
 lwnode_optgroup.add_option('--enable-external-builtin-scripts',
     action='store_true',
@@ -103,6 +103,11 @@ lwnode_optgroup.add_option('--static-escargot',
     dest='static_escargot',
     help='link to a static escargot instead of shared linking')
 
+lwnode_optgroup.add_option('--escargot-threading',
+    action='store_true',
+    dest='escargot_threading',
+    help='Enable Escargot threading')
+
 parser.add_option_group(lwnode_optgroup)
 
 def get_lwnode_gyp_options():
@@ -129,7 +134,6 @@ def get_lwnode_gyp_options():
   if options.tizen:
     args += ['-Dtarget_os=tizen']
     args += ['-Dprofile='+ str(options.profile)]
-    args += ['-Descargot_host=tizen_obs']
   else:
     args += ['-Dtarget_os=linux']
 
@@ -138,6 +142,12 @@ def get_lwnode_gyp_options():
   else:
     args += (['-Descargot_lib_type=shared_lib'])
 
+  if options.escargot_threading:
+    args += (['-Descargot_threading=1'])
+  else:
+    args += (['-Descargot_threading=0'])
+
+
   args += ['-Dnode_core_target_name=lwnode']
   args += ['-Dnode_lib_target_name=liblwnode']
 
index 2c89a249f37deabaff1f1b3228f4eaad444a1003..b8bec1e5200df91a8bfc2688c30c2235b4f7d4c9 100644 (file)
@@ -178,6 +178,18 @@ const bufferWarning = 'Buffer() is deprecated due to security and usability ' +
                       'Buffer.allocUnsafe(), or Buffer.from() methods instead.';
 
 function showFlaggedDeprecation() {
+  // @lwnode
+  // @fixme force depress DeprecationWarning until isInsideNodeModules works
+  if (bufferWarningAlreadyEmitted ||
+    ++nodeModulesCheckCounter > 10000 ||
+    (!require('internal/options').getOptionValue('--pending-deprecation'))) {
+    return;
+  }
+
+  process.emitWarning(bufferWarning, 'DeprecationWarning', 'DEP0005');
+  bufferWarningAlreadyEmitted = true;
+  return;
+
   if (bufferWarningAlreadyEmitted ||
       ++nodeModulesCheckCounter > 10000 ||
       (!require('internal/options').getOptionValue('--pending-deprecation') &&
index 9a6f73c4c973dc22d147c12fcbdd55534226ad12..74f517f3f9e99b4e34b41f3a50af2d55cc8dd519 100644 (file)
@@ -19,9 +19,7 @@ const noop = () => {};
 
 class CallTracker {
 
-  // @lwnode
-  // #callChecks = new SafeSet()
-  __callChecks = new SafeSet()
+  #callChecks = new SafeSet()
 
   calls(fn, exact = 1) {
     if (process._exiting)
@@ -42,10 +40,7 @@ class CallTracker {
       stackTrace: new Error(),
       name: fn.name || 'calls'
     };
-    // @lwnode
-    // const callChecks = this.#callChecks;
-    const callChecks = this.__callChecks;
-
+    const callChecks = this.#callChecks;
     callChecks.add(context);
 
     return function() {
@@ -66,9 +61,7 @@ class CallTracker {
 
   report() {
     const errors = [];
-    // @lwnode
-    // for (const context of this.#callChecks) {
-      for (const context of this.__callChecks) {
+    for (const context of this.#callChecks) {
       // If functions have not been called exact times
       if (context.actual !== context.exact) {
         const message = `Expected the ${context.name} function to be ` +
index 6d6ca2af629c41df68fe1a4652cf94fef30be038..4a9a5369c5b43370fd107a8baf3532abd7d0371b 100644 (file)
@@ -87,6 +87,12 @@ const rawMethods = internalBinding('process_methods');
   process.kill = wrapped.kill;
   process.exit = wrapped.exit;
 
+  // @lwnode
+  process.lwnode = wrapped.lwnode;
+  process._print = wrapped.lwnode._print;
+  process._ptr = wrapped.lwnode._ptr;
+  process._stack = wrapped.lwnode._stack;
+
   process.openStdin = function() {
     process.stdin.resume();
     return process.stdin;
index dc692441b5670f6101ff4cad451f85da48cd7728..cb035c812a9b3addc6bc0dad24177121d9d7705a 100644 (file)
@@ -504,20 +504,13 @@ ChildProcess.prototype.unref = function() {
 };
 
 class Control extends EventEmitter {
-  // @lwnode
-  // #channel = null;
-  // #refs = 0;
-  // #refExplicitlySet = false;
-  __channel = null;
-  __refs = 0;
-  __refExplicitlySet = false;
-  // end @lwnode
+  #channel = null;
+  #refs = 0;
+  #refExplicitlySet = false;
 
   constructor(channel) {
     super();
-    // @lwnode
-    // this.#channel = channel;
-    this.__channel = channel;
+    this.#channel = channel;
   }
 
   // The methods keeping track of the counter are being used to track the
@@ -525,49 +518,30 @@ class Control extends EventEmitter {
   // in progress. Once the user has explicitly requested a certain state, these
   // methods become no-ops in order to not interfere with the user's intentions.
   refCounted() {
-    // @lwnode
-    // if (++this.#refs === 1 && !this.#refExplicitlySet) {
-    //   this.#channel.ref();
-    // }
-    if (++this.__refs === 1 && !this.__refExplicitlySet) {
-      this.__channel.ref();
+    if (++this.#refs === 1 && !this.#refExplicitlySet) {
+      this.#channel.ref();
     }
-    // end @lwnode
   }
 
   unrefCounted() {
-    // @lwnode
-    // if (--this.#refs === 0 && !this.#refExplicitlySet) {
-    //   this.#channel.unref();
-    //   this.emit('unref');
-    // }
-    if (--this.__refs === 0 && !this.__refExplicitlySet) {
-      this.__channel.unref();
+    if (--this.#refs === 0 && !this.#refExplicitlySet) {
+      this.#channel.unref();
       this.emit('unref');
     }
-    // end @lwnode
   }
 
   ref() {
-    // @lwnode
-    // this.#refExplicitlySet = true;
-    // this.#channel.ref();
-    this.__refExplicitlySet = true;
-    this.__channel.ref();
+    this.#refExplicitlySet = true;
+    this.#channel.ref();
   }
 
   unref() {
-    // @lwnode
-    // this.#refExplicitlySet = true;
-    // this.#channel.unref();
-    this.__refExplicitlySet = true;
-    this.__channel.unref();
+    this.#refExplicitlySet = true;
+    this.#channel.unref();
   }
 
   get fd() {
-    // @lwnode
-    // return this.#channel ? this.#channel.fd : undefined;
-    return this.__channel ? this.__channel.fd : undefined;
+    return this.#channel ? this.#channel.fd : undefined;
   }
 }
 
diff --git a/lib/internal/child_process_origin.js b/lib/internal/child_process_origin.js
deleted file mode 100644 (file)
index cb035c8..0000000
+++ /dev/null
@@ -1,1082 +0,0 @@
-'use strict';
-
-const {
-  ArrayIsArray,
-  ObjectDefineProperty,
-  ObjectSetPrototypeOf,
-  Symbol,
-  Uint8Array,
-} = primordials;
-
-const {
-  errnoException,
-  codes: {
-    ERR_INVALID_ARG_TYPE,
-    ERR_INVALID_HANDLE_TYPE,
-    ERR_INVALID_OPT_VALUE,
-    ERR_INVALID_SYNC_FORK_INPUT,
-    ERR_IPC_CHANNEL_CLOSED,
-    ERR_IPC_DISCONNECTED,
-    ERR_IPC_ONE_PIPE,
-    ERR_IPC_SYNC_FORK,
-    ERR_MISSING_ARGS
-  }
-} = require('internal/errors');
-const { validateString, validateOneOf } = require('internal/validators');
-const EventEmitter = require('events');
-const net = require('net');
-const dgram = require('dgram');
-const inspect = require('internal/util/inspect').inspect;
-const assert = require('internal/assert');
-
-const { Process } = internalBinding('process_wrap');
-const {
-  WriteWrap,
-  kReadBytesOrError,
-  kArrayBufferOffset,
-  kLastWriteWasAsync,
-  streamBaseState
-} = internalBinding('stream_wrap');
-const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap');
-const { TCP } = internalBinding('tcp_wrap');
-const { TTY } = internalBinding('tty_wrap');
-const { UDP } = internalBinding('udp_wrap');
-const SocketList = require('internal/socket_list');
-const { owner_symbol } = require('internal/async_hooks').symbols;
-const { convertToValidSignal, deprecate } = require('internal/util');
-const { isArrayBufferView } = require('internal/util/types');
-const spawn_sync = internalBinding('spawn_sync');
-const { kStateSymbol } = require('internal/dgram');
-
-const {
-  UV_EACCES,
-  UV_EAGAIN,
-  UV_EINVAL,
-  UV_EMFILE,
-  UV_ENFILE,
-  UV_ENOENT,
-  UV_ENOSYS,
-  UV_ESRCH
-} = internalBinding('uv');
-
-const { SocketListSend, SocketListReceive } = SocketList;
-
-// Lazy loaded for startup performance and to allow monkey patching of
-// internalBinding('http_parser').HTTPParser.
-let freeParser;
-let HTTPParser;
-
-const MAX_HANDLE_RETRANSMISSIONS = 3;
-const kChannelHandle = Symbol('kChannelHandle');
-const kIsUsedAsStdio = Symbol('kIsUsedAsStdio');
-
-// This object contain function to convert TCP objects to native handle objects
-// and back again.
-const handleConversion = {
-  'net.Native': {
-    simultaneousAccepts: true,
-
-    send(message, handle, options) {
-      return handle;
-    },
-
-    got(message, handle, emit) {
-      emit(handle);
-    }
-  },
-
-  'net.Server': {
-    simultaneousAccepts: true,
-
-    send(message, server, options) {
-      return server._handle;
-    },
-
-    got(message, handle, emit) {
-      const server = new net.Server();
-      server.listen(handle, () => {
-        emit(server);
-      });
-    }
-  },
-
-  'net.Socket': {
-    send(message, socket, options) {
-      if (!socket._handle)
-        return;
-
-      // If the socket was created by net.Server
-      if (socket.server) {
-        // The worker should keep track of the socket
-        message.key = socket.server._connectionKey;
-
-        const firstTime = !this[kChannelHandle].sockets.send[message.key];
-        const socketList = getSocketList('send', this, message.key);
-
-        // The server should no longer expose a .connection property
-        // and when asked to close it should query the socket status from
-        // the workers
-        if (firstTime) socket.server._setupWorker(socketList);
-
-        // Act like socket is detached
-        if (!options.keepOpen)
-          socket.server._connections--;
-      }
-
-      const handle = socket._handle;
-
-      // Remove handle from socket object, it will be closed when the socket
-      // will be sent
-      if (!options.keepOpen) {
-        handle.onread = nop;
-        socket._handle = null;
-        socket.setTimeout(0);
-
-        if (freeParser === undefined)
-          freeParser = require('_http_common').freeParser;
-        if (HTTPParser === undefined)
-          HTTPParser = require('_http_common').HTTPParser;
-
-        // In case of an HTTP connection socket, release the associated
-        // resources
-        if (socket.parser && socket.parser instanceof HTTPParser) {
-          freeParser(socket.parser, null, socket);
-          if (socket._httpMessage)
-            socket._httpMessage.detachSocket(socket);
-        }
-      }
-
-      return handle;
-    },
-
-    postSend(message, handle, options, callback, target) {
-      // Store the handle after successfully sending it, so it can be closed
-      // when the NODE_HANDLE_ACK is received. If the handle could not be sent,
-      // just close it.
-      if (handle && !options.keepOpen) {
-        if (target) {
-          // There can only be one _pendingMessage as passing handles are
-          // processed one at a time: handles are stored in _handleQueue while
-          // waiting for the NODE_HANDLE_ACK of the current passing handle.
-          assert(!target._pendingMessage);
-          target._pendingMessage =
-              { callback, message, handle, options, retransmissions: 0 };
-        } else {
-          handle.close();
-        }
-      }
-    },
-
-    got(message, handle, emit) {
-      const socket = new net.Socket({
-        handle: handle,
-        readable: true,
-        writable: true
-      });
-
-      // If the socket was created by net.Server we will track the socket
-      if (message.key) {
-
-        // Add socket to connections list
-        const socketList = getSocketList('got', this, message.key);
-        socketList.add({
-          socket: socket
-        });
-      }
-
-      emit(socket);
-    }
-  },
-
-  'dgram.Native': {
-    simultaneousAccepts: false,
-
-    send(message, handle, options) {
-      return handle;
-    },
-
-    got(message, handle, emit) {
-      emit(handle);
-    }
-  },
-
-  'dgram.Socket': {
-    simultaneousAccepts: false,
-
-    send(message, socket, options) {
-      message.dgramType = socket.type;
-
-      return socket[kStateSymbol].handle;
-    },
-
-    got(message, handle, emit) {
-      const socket = new dgram.Socket(message.dgramType);
-
-      socket.bind(handle, () => {
-        emit(socket);
-      });
-    }
-  }
-};
-
-function stdioStringToArray(stdio, channel) {
-  const options = [];
-
-  switch (stdio) {
-    case 'ignore':
-    case 'pipe': options.push(stdio, stdio, stdio); break;
-    case 'inherit': options.push(0, 1, 2); break;
-    default:
-      throw new ERR_INVALID_OPT_VALUE('stdio', stdio);
-  }
-
-  if (channel) options.push(channel);
-
-  return options;
-}
-
-function ChildProcess() {
-  EventEmitter.call(this);
-
-  this._closesNeeded = 1;
-  this._closesGot = 0;
-  this.connected = false;
-
-  this.signalCode = null;
-  this.exitCode = null;
-  this.killed = false;
-  this.spawnfile = null;
-
-  this._handle = new Process();
-  this._handle[owner_symbol] = this;
-
-  this._handle.onexit = (exitCode, signalCode) => {
-    if (signalCode) {
-      this.signalCode = signalCode;
-    } else {
-      this.exitCode = exitCode;
-    }
-
-    if (this.stdin) {
-      this.stdin.destroy();
-    }
-
-    this._handle.close();
-    this._handle = null;
-
-    if (exitCode < 0) {
-      const syscall = this.spawnfile ? 'spawn ' + this.spawnfile : 'spawn';
-      const err = errnoException(exitCode, syscall);
-
-      if (this.spawnfile)
-        err.path = this.spawnfile;
-
-      err.spawnargs = this.spawnargs.slice(1);
-      this.emit('error', err);
-    } else {
-      this.emit('exit', this.exitCode, this.signalCode);
-    }
-
-    // If any of the stdio streams have not been touched,
-    // then pull all the data through so that it can get the
-    // eof and emit a 'close' event.
-    // Do it on nextTick so that the user has one last chance
-    // to consume the output, if for example they only want to
-    // start reading the data once the process exits.
-    process.nextTick(flushStdio, this);
-
-    maybeClose(this);
-  };
-}
-ObjectSetPrototypeOf(ChildProcess.prototype, EventEmitter.prototype);
-ObjectSetPrototypeOf(ChildProcess, EventEmitter);
-
-
-function flushStdio(subprocess) {
-  const stdio = subprocess.stdio;
-
-  if (stdio == null) return;
-
-  for (let i = 0; i < stdio.length; i++) {
-    const stream = stdio[i];
-    // TODO(addaleax): This doesn't necessarily account for all the ways in
-    // which data can be read from a stream, e.g. being consumed on the
-    // native layer directly as a StreamBase.
-    if (!stream || !stream.readable || stream[kIsUsedAsStdio]) {
-      continue;
-    }
-    stream.resume();
-  }
-}
-
-
-function createSocket(pipe, readable) {
-  return net.Socket({ handle: pipe, readable, writable: !readable });
-}
-
-
-function getHandleWrapType(stream) {
-  if (stream instanceof Pipe) return 'pipe';
-  if (stream instanceof TTY) return 'tty';
-  if (stream instanceof TCP) return 'tcp';
-  if (stream instanceof UDP) return 'udp';
-
-  return false;
-}
-
-function closePendingHandle(target) {
-  target._pendingMessage.handle.close();
-  target._pendingMessage = null;
-}
-
-
-ChildProcess.prototype.spawn = function(options) {
-  let i = 0;
-
-  if (options === null || typeof options !== 'object') {
-    throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
-  }
-
-  // If no `stdio` option was given - use default
-  let stdio = options.stdio || 'pipe';
-
-  stdio = getValidStdio(stdio, false);
-
-  const ipc = stdio.ipc;
-  const ipcFd = stdio.ipcFd;
-  stdio = options.stdio = stdio.stdio;
-
-
-  validateOneOf(options.serialization, 'options.serialization',
-                [undefined, 'json', 'advanced'], true);
-  const serialization = options.serialization || 'json';
-
-  if (ipc !== undefined) {
-    // Let child process know about opened IPC channel
-    if (options.envPairs === undefined)
-      options.envPairs = [];
-    else if (!ArrayIsArray(options.envPairs)) {
-      throw new ERR_INVALID_ARG_TYPE('options.envPairs',
-                                     'Array',
-                                     options.envPairs);
-    }
-
-    options.envPairs.push(`NODE_CHANNEL_FD=${ipcFd}`);
-    options.envPairs.push(`NODE_CHANNEL_SERIALIZATION_MODE=${serialization}`);
-  }
-
-  validateString(options.file, 'options.file');
-  this.spawnfile = options.file;
-
-  if (ArrayIsArray(options.args))
-    this.spawnargs = options.args;
-  else if (options.args === undefined)
-    this.spawnargs = [];
-  else
-    throw new ERR_INVALID_ARG_TYPE('options.args', 'Array', options.args);
-
-  const err = this._handle.spawn(options);
-
-  // Run-time errors should emit an error, not throw an exception.
-  if (err === UV_EACCES ||
-      err === UV_EAGAIN ||
-      err === UV_EMFILE ||
-      err === UV_ENFILE ||
-      err === UV_ENOENT) {
-    process.nextTick(onErrorNT, this, err);
-
-    // There is no point in continuing when we've hit EMFILE or ENFILE
-    // because we won't be able to set up the stdio file descriptors.
-    if (err === UV_EMFILE || err === UV_ENFILE)
-      return err;
-  } else if (err) {
-    // Close all opened fds on error
-    for (i = 0; i < stdio.length; i++) {
-      const stream = stdio[i];
-      if (stream.type === 'pipe') {
-        stream.handle.close();
-      }
-    }
-
-    this._handle.close();
-    this._handle = null;
-    throw errnoException(err, 'spawn');
-  }
-
-  this.pid = this._handle.pid;
-
-  for (i = 0; i < stdio.length; i++) {
-    const stream = stdio[i];
-    if (stream.type === 'ignore') continue;
-
-    if (stream.ipc) {
-      this._closesNeeded++;
-      continue;
-    }
-
-    // The stream is already cloned and piped, thus stop its readable side,
-    // otherwise we might attempt to read from the stream when at the same time
-    // the child process does.
-    if (stream.type === 'wrap') {
-      stream.handle.reading = false;
-      stream.handle.readStop();
-      stream._stdio.pause();
-      stream._stdio.readableFlowing = false;
-      stream._stdio._readableState.reading = false;
-      stream._stdio[kIsUsedAsStdio] = true;
-      continue;
-    }
-
-    if (stream.handle) {
-      // When i === 0 - we're dealing with stdin
-      // (which is the only one writable pipe).
-      stream.socket = createSocket(this.pid !== 0 ?
-        stream.handle : null, i > 0);
-
-      if (i > 0 && this.pid !== 0) {
-        this._closesNeeded++;
-        stream.socket.on('close', () => {
-          maybeClose(this);
-        });
-      }
-    }
-  }
-
-  this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ?
-    stdio[0].socket : null;
-  this.stdout = stdio.length >= 2 && stdio[1].socket !== undefined ?
-    stdio[1].socket : null;
-  this.stderr = stdio.length >= 3 && stdio[2].socket !== undefined ?
-    stdio[2].socket : null;
-
-  this.stdio = [];
-
-  for (i = 0; i < stdio.length; i++)
-    this.stdio.push(stdio[i].socket === undefined ? null : stdio[i].socket);
-
-  // Add .send() method and start listening for IPC data
-  if (ipc !== undefined) setupChannel(this, ipc, serialization);
-
-  return err;
-};
-
-
-function onErrorNT(self, err) {
-  self._handle.onexit(err);
-}
-
-
-ChildProcess.prototype.kill = function(sig) {
-
-  const signal = sig === 0 ? sig :
-    convertToValidSignal(sig === undefined ? 'SIGTERM' : sig);
-
-  if (this._handle) {
-    const err = this._handle.kill(signal);
-    if (err === 0) {
-      /* Success. */
-      this.killed = true;
-      return true;
-    }
-    if (err === UV_ESRCH) {
-      /* Already dead. */
-    } else if (err === UV_EINVAL || err === UV_ENOSYS) {
-      /* The underlying platform doesn't support this signal. */
-      throw errnoException(err, 'kill');
-    } else {
-      /* Other error, almost certainly EPERM. */
-      this.emit('error', errnoException(err, 'kill'));
-    }
-  }
-
-  /* Kill didn't succeed. */
-  return false;
-};
-
-
-ChildProcess.prototype.ref = function() {
-  if (this._handle) this._handle.ref();
-};
-
-
-ChildProcess.prototype.unref = function() {
-  if (this._handle) this._handle.unref();
-};
-
-class Control extends EventEmitter {
-  #channel = null;
-  #refs = 0;
-  #refExplicitlySet = false;
-
-  constructor(channel) {
-    super();
-    this.#channel = channel;
-  }
-
-  // The methods keeping track of the counter are being used to track the
-  // listener count on the child process object as well as when writes are
-  // in progress. Once the user has explicitly requested a certain state, these
-  // methods become no-ops in order to not interfere with the user's intentions.
-  refCounted() {
-    if (++this.#refs === 1 && !this.#refExplicitlySet) {
-      this.#channel.ref();
-    }
-  }
-
-  unrefCounted() {
-    if (--this.#refs === 0 && !this.#refExplicitlySet) {
-      this.#channel.unref();
-      this.emit('unref');
-    }
-  }
-
-  ref() {
-    this.#refExplicitlySet = true;
-    this.#channel.ref();
-  }
-
-  unref() {
-    this.#refExplicitlySet = true;
-    this.#channel.unref();
-  }
-
-  get fd() {
-    return this.#channel ? this.#channel.fd : undefined;
-  }
-}
-
-const channelDeprecationMsg = '_channel is deprecated. ' +
-                              'Use ChildProcess.channel instead.';
-
-let serialization;
-function setupChannel(target, channel, serializationMode) {
-  const control = new Control(channel);
-  target.channel = control;
-  target[kChannelHandle] = channel;
-
-  ObjectDefineProperty(target, '_channel', {
-    get: deprecate(() => {
-      return target.channel;
-    }, channelDeprecationMsg, 'DEP0129'),
-    set: deprecate((val) => {
-      target.channel = val;
-    }, channelDeprecationMsg, 'DEP0129'),
-    configurable: true,
-    enumerable: false
-  });
-
-  target._handleQueue = null;
-  target._pendingMessage = null;
-
-  if (serialization === undefined)
-    serialization = require('internal/child_process/serialization');
-  const {
-    initMessageChannel,
-    parseChannelMessages,
-    writeChannelMessage
-  } = serialization[serializationMode];
-
-  let pendingHandle = null;
-  initMessageChannel(channel);
-  channel.pendingHandle = null;
-  channel.onread = function(arrayBuffer) {
-    const recvHandle = channel.pendingHandle;
-    channel.pendingHandle = null;
-    if (arrayBuffer) {
-      const nread = streamBaseState[kReadBytesOrError];
-      const offset = streamBaseState[kArrayBufferOffset];
-      const pool = new Uint8Array(arrayBuffer, offset, nread);
-      if (recvHandle)
-        pendingHandle = recvHandle;
-
-      for (const message of parseChannelMessages(channel, pool)) {
-        // There will be at most one NODE_HANDLE message in every chunk we
-        // read because SCM_RIGHTS messages don't get coalesced. Make sure
-        // that we deliver the handle with the right message however.
-        if (isInternal(message)) {
-          if (message.cmd === 'NODE_HANDLE') {
-            handleMessage(message, pendingHandle, true);
-            pendingHandle = null;
-          } else {
-            handleMessage(message, undefined, true);
-          }
-        } else {
-          handleMessage(message, undefined, false);
-        }
-      }
-    } else {
-      this.buffering = false;
-      target.disconnect();
-      channel.onread = nop;
-      channel.close();
-      target.channel = null;
-      maybeClose(target);
-    }
-  };
-
-  // Object where socket lists will live
-  channel.sockets = { got: {}, send: {} };
-
-  // Handlers will go through this
-  target.on('internalMessage', function(message, handle) {
-    // Once acknowledged - continue sending handles.
-    if (message.cmd === 'NODE_HANDLE_ACK' ||
-        message.cmd === 'NODE_HANDLE_NACK') {
-
-      if (target._pendingMessage) {
-        if (message.cmd === 'NODE_HANDLE_ACK') {
-          closePendingHandle(target);
-        } else if (target._pendingMessage.retransmissions++ ===
-                   MAX_HANDLE_RETRANSMISSIONS) {
-          closePendingHandle(target);
-          process.emitWarning('Handle did not reach the receiving process ' +
-                              'correctly', 'SentHandleNotReceivedWarning');
-        }
-      }
-
-      assert(ArrayIsArray(target._handleQueue));
-      const queue = target._handleQueue;
-      target._handleQueue = null;
-
-      if (target._pendingMessage) {
-        target._send(target._pendingMessage.message,
-                     target._pendingMessage.handle,
-                     target._pendingMessage.options,
-                     target._pendingMessage.callback);
-      }
-
-      for (let i = 0; i < queue.length; i++) {
-        const args = queue[i];
-        target._send(args.message, args.handle, args.options, args.callback);
-      }
-
-      // Process a pending disconnect (if any).
-      if (!target.connected && target.channel && !target._handleQueue)
-        target._disconnect();
-
-      return;
-    }
-
-    if (message.cmd !== 'NODE_HANDLE') return;
-
-    // It is possible that the handle is not received because of some error on
-    // ancillary data reception such as MSG_CTRUNC. In this case, report the
-    // sender about it by sending a NODE_HANDLE_NACK message.
-    if (!handle)
-      return target._send({ cmd: 'NODE_HANDLE_NACK' }, null, true);
-
-    // Acknowledge handle receival. Don't emit error events (for example if
-    // the other side has disconnected) because this call to send() is not
-    // initiated by the user and it shouldn't be fatal to be unable to ACK
-    // a message.
-    target._send({ cmd: 'NODE_HANDLE_ACK' }, null, true);
-
-    const obj = handleConversion[message.type];
-
-    // Update simultaneous accepts on Windows
-    if (process.platform === 'win32') {
-      handle.setSimultaneousAccepts(false);
-    }
-
-    // Convert handle object
-    obj.got.call(this, message, handle, (handle) => {
-      handleMessage(message.msg, handle, isInternal(message.msg));
-    });
-  });
-
-  target.send = function(message, handle, options, callback) {
-    if (typeof handle === 'function') {
-      callback = handle;
-      handle = undefined;
-      options = undefined;
-    } else if (typeof options === 'function') {
-      callback = options;
-      options = undefined;
-    } else if (options !== undefined &&
-               (options === null || typeof options !== 'object')) {
-      throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
-    }
-
-    options = { swallowErrors: false, ...options };
-
-    if (this.connected) {
-      return this._send(message, handle, options, callback);
-    }
-    const ex = new ERR_IPC_CHANNEL_CLOSED();
-    if (typeof callback === 'function') {
-      process.nextTick(callback, ex);
-    } else {
-      process.nextTick(() => this.emit('error', ex));
-    }
-    return false;
-  };
-
-  target._send = function(message, handle, options, callback) {
-    assert(this.connected || this.channel);
-
-    if (message === undefined)
-      throw new ERR_MISSING_ARGS('message');
-
-    // Non-serializable messages should not reach the remote
-    // end point; as any failure in the stringification there
-    // will result in error message that is weakly consumable.
-    // So perform a sanity check on message prior to sending.
-    if (typeof message !== 'string' &&
-        typeof message !== 'object' &&
-        typeof message !== 'number' &&
-        typeof message !== 'boolean') {
-      throw new ERR_INVALID_ARG_TYPE(
-        'message', ['string', 'object', 'number', 'boolean'], message);
-    }
-
-    // Support legacy function signature
-    if (typeof options === 'boolean') {
-      options = { swallowErrors: options };
-    }
-
-    let obj;
-
-    // Package messages with a handle object
-    if (handle) {
-      // This message will be handled by an internalMessage event handler
-      message = {
-        cmd: 'NODE_HANDLE',
-        type: null,
-        msg: message
-      };
-
-      if (handle instanceof net.Socket) {
-        message.type = 'net.Socket';
-      } else if (handle instanceof net.Server) {
-        message.type = 'net.Server';
-      } else if (handle instanceof TCP || handle instanceof Pipe) {
-        message.type = 'net.Native';
-      } else if (handle instanceof dgram.Socket) {
-        message.type = 'dgram.Socket';
-      } else if (handle instanceof UDP) {
-        message.type = 'dgram.Native';
-      } else {
-        throw new ERR_INVALID_HANDLE_TYPE();
-      }
-
-      // Queue-up message and handle if we haven't received ACK yet.
-      if (this._handleQueue) {
-        this._handleQueue.push({
-          callback: callback,
-          handle: handle,
-          options: options,
-          message: message.msg,
-        });
-        return this._handleQueue.length === 1;
-      }
-
-      obj = handleConversion[message.type];
-
-      // convert TCP object to native handle object
-      handle = handleConversion[message.type].send.call(target,
-                                                        message,
-                                                        handle,
-                                                        options);
-
-      // If handle was sent twice, or it is impossible to get native handle
-      // out of it - just send a text without the handle.
-      if (!handle)
-        message = message.msg;
-
-      // Update simultaneous accepts on Windows
-      if (obj.simultaneousAccepts && process.platform === 'win32') {
-        handle.setSimultaneousAccepts(true);
-      }
-    } else if (this._handleQueue &&
-               !(message && (message.cmd === 'NODE_HANDLE_ACK' ||
-                             message.cmd === 'NODE_HANDLE_NACK'))) {
-      // Queue request anyway to avoid out-of-order messages.
-      this._handleQueue.push({
-        callback: callback,
-        handle: null,
-        options: options,
-        message: message,
-      });
-      return this._handleQueue.length === 1;
-    }
-
-    const req = new WriteWrap();
-
-    const err = writeChannelMessage(channel, req, message, handle);
-    const wasAsyncWrite = streamBaseState[kLastWriteWasAsync];
-
-    if (err === 0) {
-      if (handle) {
-        if (!this._handleQueue)
-          this._handleQueue = [];
-        if (obj && obj.postSend)
-          obj.postSend(message, handle, options, callback, target);
-      }
-
-      if (wasAsyncWrite) {
-        req.oncomplete = () => {
-          control.unrefCounted();
-          if (typeof callback === 'function')
-            callback(null);
-        };
-        control.refCounted();
-      } else if (typeof callback === 'function') {
-        process.nextTick(callback, null);
-      }
-    } else {
-      // Cleanup handle on error
-      if (obj && obj.postSend)
-        obj.postSend(message, handle, options, callback);
-
-      if (!options.swallowErrors) {
-        const ex = errnoException(err, 'write');
-        if (typeof callback === 'function') {
-          process.nextTick(callback, ex);
-        } else {
-          process.nextTick(() => this.emit('error', ex));
-        }
-      }
-    }
-
-    /* If the master is > 2 read() calls behind, please stop sending. */
-    return channel.writeQueueSize < (65536 * 2);
-  };
-
-  // Connected will be set to false immediately when a disconnect() is
-  // requested, even though the channel might still be alive internally to
-  // process queued messages. The three states are distinguished as follows:
-  // - disconnect() never requested: channel is not null and connected
-  //   is true
-  // - disconnect() requested, messages in the queue: channel is not null
-  //   and connected is false
-  // - disconnect() requested, channel actually disconnected: channel is
-  //   null and connected is false
-  target.connected = true;
-
-  target.disconnect = function() {
-    if (!this.connected) {
-      this.emit('error', new ERR_IPC_DISCONNECTED());
-      return;
-    }
-
-    // Do not allow any new messages to be written.
-    this.connected = false;
-
-    // If there are no queued messages, disconnect immediately. Otherwise,
-    // postpone the disconnect so that it happens internally after the
-    // queue is flushed.
-    if (!this._handleQueue)
-      this._disconnect();
-  };
-
-  target._disconnect = function() {
-    assert(this.channel);
-
-    // This marks the fact that the channel is actually disconnected.
-    this.channel = null;
-    this[kChannelHandle] = null;
-
-    if (this._pendingMessage)
-      closePendingHandle(this);
-
-    let fired = false;
-    function finish() {
-      if (fired) return;
-      fired = true;
-
-      channel.close();
-      target.emit('disconnect');
-    }
-
-    // If a message is being read, then wait for it to complete.
-    if (channel.buffering) {
-      this.once('message', finish);
-      this.once('internalMessage', finish);
-
-      return;
-    }
-
-    process.nextTick(finish);
-  };
-
-  function emit(event, message, handle) {
-    target.emit(event, message, handle);
-  }
-
-  function handleMessage(message, handle, internal) {
-    if (!target.channel)
-      return;
-
-    const eventName = (internal ? 'internalMessage' : 'message');
-
-    process.nextTick(emit, eventName, message, handle);
-  }
-
-  channel.readStart();
-  return control;
-}
-
-const INTERNAL_PREFIX = 'NODE_';
-function isInternal(message) {
-  return (message !== null &&
-          typeof message === 'object' &&
-          typeof message.cmd === 'string' &&
-          message.cmd.length > INTERNAL_PREFIX.length &&
-          message.cmd.slice(0, INTERNAL_PREFIX.length) === INTERNAL_PREFIX);
-}
-
-function nop() { }
-
-function getValidStdio(stdio, sync) {
-  let ipc;
-  let ipcFd;
-
-  // Replace shortcut with an array
-  if (typeof stdio === 'string') {
-    stdio = stdioStringToArray(stdio);
-  } else if (!ArrayIsArray(stdio)) {
-    throw new ERR_INVALID_OPT_VALUE('stdio', stdio);
-  }
-
-  // At least 3 stdio will be created
-  // Don't concat() a new Array() because it would be sparse, and
-  // stdio.reduce() would skip the sparse elements of stdio.
-  // See https://stackoverflow.com/a/5501711/3561
-  while (stdio.length < 3) stdio.push(undefined);
-
-  // Translate stdio into C++-readable form
-  // (i.e. PipeWraps or fds)
-  stdio = stdio.reduce((acc, stdio, i) => {
-    function cleanup() {
-      for (let i = 0; i < acc.length; i++) {
-        if ((acc[i].type === 'pipe' || acc[i].type === 'ipc') && acc[i].handle)
-          acc[i].handle.close();
-      }
-    }
-
-    // Defaults
-    if (stdio == null) {
-      stdio = i < 3 ? 'pipe' : 'ignore';
-    }
-
-    if (stdio === 'ignore') {
-      acc.push({ type: 'ignore' });
-    } else if (stdio === 'pipe' || (typeof stdio === 'number' && stdio < 0)) {
-      const a = {
-        type: 'pipe',
-        readable: i === 0,
-        writable: i !== 0
-      };
-
-      if (!sync)
-        a.handle = new Pipe(PipeConstants.SOCKET);
-
-      acc.push(a);
-    } else if (stdio === 'ipc') {
-      if (sync || ipc !== undefined) {
-        // Cleanup previously created pipes
-        cleanup();
-        if (!sync)
-          throw new ERR_IPC_ONE_PIPE();
-        else
-          throw new ERR_IPC_SYNC_FORK();
-      }
-
-      ipc = new Pipe(PipeConstants.IPC);
-      ipcFd = i;
-
-      acc.push({
-        type: 'pipe',
-        handle: ipc,
-        ipc: true
-      });
-    } else if (stdio === 'inherit') {
-      acc.push({
-        type: 'inherit',
-        fd: i
-      });
-    } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') {
-      acc.push({
-        type: 'fd',
-        fd: typeof stdio === 'number' ? stdio : stdio.fd
-      });
-    } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) ||
-               getHandleWrapType(stdio._handle)) {
-      const handle = getHandleWrapType(stdio) ?
-        stdio :
-        getHandleWrapType(stdio.handle) ? stdio.handle : stdio._handle;
-
-      acc.push({
-        type: 'wrap',
-        wrapType: getHandleWrapType(handle),
-        handle: handle,
-        _stdio: stdio
-      });
-    } else if (isArrayBufferView(stdio) || typeof stdio === 'string') {
-      if (!sync) {
-        cleanup();
-        throw new ERR_INVALID_SYNC_FORK_INPUT(inspect(stdio));
-      }
-    } else {
-      // Cleanup
-      cleanup();
-      throw new ERR_INVALID_OPT_VALUE('stdio', stdio);
-    }
-
-    return acc;
-  }, []);
-
-  return { stdio, ipc, ipcFd };
-}
-
-
-function getSocketList(type, worker, key) {
-  const sockets = worker[kChannelHandle].sockets[type];
-  let socketList = sockets[key];
-  if (!socketList) {
-    const Construct = type === 'send' ? SocketListSend : SocketListReceive;
-    socketList = sockets[key] = new Construct(worker, key);
-  }
-  return socketList;
-}
-
-
-function maybeClose(subprocess) {
-  subprocess._closesGot++;
-
-  if (subprocess._closesGot === subprocess._closesNeeded) {
-    subprocess.emit('close', subprocess.exitCode, subprocess.signalCode);
-  }
-}
-
-function spawnSync(options) {
-  const result = spawn_sync.spawn(options);
-
-  if (result.output && options.encoding && options.encoding !== 'buffer') {
-    for (let i = 0; i < result.output.length; i++) {
-      if (!result.output[i])
-        continue;
-      result.output[i] = result.output[i].toString(options.encoding);
-    }
-  }
-
-  result.stdout = result.output && result.output[1];
-  result.stderr = result.output && result.output[2];
-
-  if (result.error) {
-    result.error = errnoException(result.error, 'spawnSync ' + options.file);
-    result.error.path = options.file;
-    result.error.spawnargs = options.args.slice(1);
-  }
-
-  return result;
-}
-
-module.exports = {
-  ChildProcess,
-  kChannelHandle,
-  setupChannel,
-  getValidStdio,
-  stdioStringToArray,
-  spawnSync
-};
index e0022be405d4184a34475ff96195d564486e8fad..6deb8314a41bbb5203019094580dbca605b5042d 100644 (file)
@@ -19,17 +19,11 @@ const kHandle = Symbol('kHandle');
 // record various metrics. This Histogram class provides a
 // generally read-only view of the internal histogram.
 class Histogram {
-  // @lwnode
-  // #handle = undefined;
-  // #map = new Map();
-  __handle = undefined;
-  __map = new Map();
-  // end @lwnode
+  #handle = undefined;
+  #map = new Map();
 
   constructor(internal) {
-    // @lwnode
-    // this.#handle = internal;
-    this.__handle = internal;
+    this.#handle = internal;
   }
 
   [kInspect]() {
@@ -45,33 +39,23 @@ class Histogram {
   }
 
   get min() {
-    // @lwnode
-    // return this.#handle ? this.#handle.min() : undefined;
-    return this.__handle ? this.__handle.min() : undefined;
+    return this.#handle ? this.#handle.min() : undefined;
   }
 
   get max() {
-    // @lwnode
-    // return this.#handle ? this.#handle.max() : undefined;
-    return this.__handle ? this.__handle.max() : undefined;
+    return this.#handle ? this.#handle.max() : undefined;
   }
 
   get mean() {
-    // @lwnode
-    // return this.#handle ? this.#handle.mean() : undefined;
-    return this.__handle ? this.__handle.mean() : undefined;
+    return this.#handle ? this.#handle.mean() : undefined;
   }
 
   get exceeds() {
-    // @lwnode
-    // return this.#handle ? this.#handle.exceeds() : undefined;
-    return this.__handle ? this.__handle.exceeds() : undefined;
+    return this.#handle ? this.#handle.exceeds() : undefined;
   }
 
   get stddev() {
-    // @lwnode
-    // return this.#handle ? this.#handle.stddev() : undefined;
-    return this.__handle ? this.__handle.stddev() : undefined;
+    return this.#handle ? this.#handle.stddev() : undefined;
   }
 
   percentile(percentile) {
@@ -81,42 +65,26 @@ class Histogram {
     if (percentile <= 0 || percentile > 100)
       throw new ERR_INVALID_ARG_VALUE.RangeError('percentile', percentile);
 
-    // @lwnode
-    // return this.#handle ? this.#handle.percentile(percentile) : undefined;
-    return this.__handle ? this.__handle.percentile(percentile) : undefined;
+    return this.#handle ? this.#handle.percentile(percentile) : undefined;
   }
 
   get percentiles() {
-    // @lwnode
-    // this.#map.clear();
-    // if (this.#handle)
-    //   this.#handle.percentiles(this.#map);
-    // return this.#map;
-    this.__map.clear();
-    if (this.__handle)
-      this.__handle.percentiles(this.__map);
-    return this.__map;
-    // end @lwnode
+    this.#map.clear();
+    if (this.#handle)
+      this.#handle.percentiles(this.#map);
+    return this.#map;
   }
 
   reset() {
-    // @lwnode
-    // if (this.#handle)
-    //   this.#handle.reset();
-    if (this.__handle)
-      this.__handle.reset();
-    // end @lwnode
+    if (this.#handle)
+      this.#handle.reset();
   }
 
   [kDestroy]() {
-    // @lwnode
-    // this.#handle = undefined;
-    this.__handle = undefined;
+    this.#handle = undefined;
   }
 
-  // @lwnode
-  //get [kHandle]() { return this.#handle; }
-  get [kHandle]() { return this.__handle; }
+  get [kHandle]() { return this.#handle; }
 }
 
 module.exports = {
diff --git a/lib/internal/histogram_origin.js b/lib/internal/histogram_origin.js
deleted file mode 100644 (file)
index 6deb831..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-'use strict';
-
-const {
-  customInspectSymbol: kInspect,
-} = require('internal/util');
-
-const { format } = require('util');
-const { Map, Symbol } = primordials;
-
-const {
-  ERR_INVALID_ARG_TYPE,
-  ERR_INVALID_ARG_VALUE,
-} = require('internal/errors').codes;
-
-const kDestroy = Symbol('kDestroy');
-const kHandle = Symbol('kHandle');
-
-// Histograms are created internally by Node.js and used to
-// record various metrics. This Histogram class provides a
-// generally read-only view of the internal histogram.
-class Histogram {
-  #handle = undefined;
-  #map = new Map();
-
-  constructor(internal) {
-    this.#handle = internal;
-  }
-
-  [kInspect]() {
-    const obj = {
-      min: this.min,
-      max: this.max,
-      mean: this.mean,
-      exceeds: this.exceeds,
-      stddev: this.stddev,
-      percentiles: this.percentiles,
-    };
-    return `Histogram ${format(obj)}`;
-  }
-
-  get min() {
-    return this.#handle ? this.#handle.min() : undefined;
-  }
-
-  get max() {
-    return this.#handle ? this.#handle.max() : undefined;
-  }
-
-  get mean() {
-    return this.#handle ? this.#handle.mean() : undefined;
-  }
-
-  get exceeds() {
-    return this.#handle ? this.#handle.exceeds() : undefined;
-  }
-
-  get stddev() {
-    return this.#handle ? this.#handle.stddev() : undefined;
-  }
-
-  percentile(percentile) {
-    if (typeof percentile !== 'number')
-      throw new ERR_INVALID_ARG_TYPE('percentile', 'number', percentile);
-
-    if (percentile <= 0 || percentile > 100)
-      throw new ERR_INVALID_ARG_VALUE.RangeError('percentile', percentile);
-
-    return this.#handle ? this.#handle.percentile(percentile) : undefined;
-  }
-
-  get percentiles() {
-    this.#map.clear();
-    if (this.#handle)
-      this.#handle.percentiles(this.#map);
-    return this.#map;
-  }
-
-  reset() {
-    if (this.#handle)
-      this.#handle.reset();
-  }
-
-  [kDestroy]() {
-    this.#handle = undefined;
-  }
-
-  get [kHandle]() { return this.#handle; }
-}
-
-module.exports = {
-  Histogram,
-  kDestroy,
-  kHandle,
-};
index b8f03ffef1939bc514fe1f62bb5743ccde9f54b5..c4f1e2c0352493d989cb95ae969aad94233cf867 100644 (file)
@@ -225,8 +225,47 @@ function wrapProcessMethods(binding) {
     };
   }
 
+  // @lwnode
+  const lwnode = {
+    _print: (...args) => {
+      if (binding.print) {
+        binding.print.apply(null, args);
+      }
+    },
+    _ptr: (...args) => {
+      if (binding.print) {
+        binding.print.ptr.apply(null, args);
+      }
+    },
+    _stack: (...args) => {
+      if (binding.print) {
+        binding.print.stack.apply(null, args);
+      }
+    },
+    PssUsage: (...args) => {
+      if (binding.PssUsage) {
+        return binding.PssUsage.apply(null, args);
+      }
+    },
+    PssSwapUsage: (...args) => {
+      if (binding.PssSwapUsage) {
+        return binding.PssSwapUsage.apply(null, args);
+      }
+    },
+    RssUsage: (...args) => {
+      if (binding.PssUsage) {
+        return binding.RssUsage.apply(null, args);
+      }
+    },
+    MemSnapshot: (...args) => {
+      if (binding.MemSnapshot) {
+        return binding.MemSnapshot.apply(null, args);
+      }
+    },
+  };
 
   return {
+    lwnode,
     _rawDebug,
     hrtime,
     hrtimeBigInt,
index e04f0a54f0eb3c514b4e72626ade677843f9fd5e..7d21e02429a08672e6b80dcf3d138dab81b4bccb 100644 (file)
@@ -121,11 +121,10 @@ class StringCharIterator {
  * @param {SourceMapV3} payload
  */
 class SourceMap {
-  // @lwnode
-  // #payload;
-  // #mappings = [];
-  // #sources = {};
-  // #sourceContentByURL = {};
+  #payload;
+  #mappings = [];
+  #sources = {};
+  #sourceContentByURL = {};
 
   /**
    * @constructor
@@ -139,42 +138,36 @@ class SourceMap {
       for (let i = 0; i < base64Digits.length; ++i)
         base64Map[base64Digits[i]] = i;
     }
-
-    this.payload = undefined;
-    this.mappings = [];
-    this.sources = {};
-
-    this.sourceContentByURL = {};
-    this.payload = cloneSourceMapV3(payload);
-    this.parseMappingPayload();
+    this.#payload = cloneSourceMapV3(payload);
+    this.#parseMappingPayload();
   }
 
   /**
    * @return {Object} raw source map v3 payload.
    */
   get payload() {
-    return cloneSourceMapV3(this.payload);
+    return cloneSourceMapV3(this.#payload);
   }
 
   /**
    * @param {SourceMapV3} mappingPayload
    */
-  parseMappingPayload() {
-    if (this.payload.sections) {
-      this.parseSections(this.payload.sections);
+  #parseMappingPayload = () => {
+    if (this.#payload.sections) {
+      this.#parseSections(this.#payload.sections);
     } else {
-      this.parseMap(this.payload, 0, 0);
+      this.#parseMap(this.#payload, 0, 0);
     }
-    this.mappings.sort(compareSourceMapEntry);
+    this.#mappings.sort(compareSourceMapEntry);
   }
 
   /**
    * @param {Array.<SourceMapV3.Section>} sections
    */
-   parseSections(sections) {
+  #parseSections = (sections) => {
     for (let i = 0; i < sections.length; ++i) {
       const section = sections[i];
-      this.parseMap(section.map, section.offset.line, section.offset.column);
+      this.#parseMap(section.map, section.offset.line, section.offset.column);
     }
   }
 
@@ -185,11 +178,11 @@ class SourceMap {
    */
   findEntry(lineNumber, columnNumber) {
     let first = 0;
-    let count = this.mappings.length;
+    let count = this.#mappings.length;
     while (count > 1) {
       const step = count >> 1;
       const middle = first + step;
-      const mapping = this.mappings[middle];
+      const mapping = this.#mappings[middle];
       if (lineNumber < mapping[0] ||
           (lineNumber === mapping[0] && columnNumber < mapping[1])) {
         count = step;
@@ -198,7 +191,7 @@ class SourceMap {
         count -= step;
       }
     }
-    const entry = this.mappings[first];
+    const entry = this.#mappings[first];
     if (!first && entry && (lineNumber < entry[0] ||
         (lineNumber === entry[0] && columnNumber < entry[1]))) {
       return {};
@@ -217,7 +210,7 @@ class SourceMap {
   /**
    * @override
    */
-   parseMap(map, lineNumber, columnNumber) {
+  #parseMap = (map, lineNumber, columnNumber) => {
     let sourceIndex = 0;
     let sourceLineNumber = 0;
     let sourceColumnNumber = 0;
@@ -228,10 +221,10 @@ class SourceMap {
       const url = map.sources[i];
       originalToCanonicalURLMap[url] = url;
       sources.push(url);
-      this.sources[url] = true;
+      this.#sources[url] = true;
 
       if (map.sourcesContent && map.sourcesContent[i])
-        this.sourceContentByURL[url] = map.sourcesContent[i];
+        this.#sourceContentByURL[url] = map.sourcesContent[i];
     }
 
     const stringCharIterator = new StringCharIterator(map.mappings);
@@ -252,7 +245,7 @@ class SourceMap {
 
       columnNumber += decodeVLQ(stringCharIterator);
       if (isSeparator(stringCharIterator.peek())) {
-        this.mappings.push([lineNumber, columnNumber]);
+        this.#mappings.push([lineNumber, columnNumber]);
         continue;
       }
 
@@ -267,7 +260,7 @@ class SourceMap {
         // Unused index into the names list.
         decodeVLQ(stringCharIterator);
 
-      this.mappings.push([lineNumber, columnNumber, sourceURL,
+      this.#mappings.push([lineNumber, columnNumber, sourceURL,
                            sourceLineNumber, sourceColumnNumber]);
     }
   };
diff --git a/lib/internal/source_map/source_map.origin.js b/lib/internal/source_map/source_map.origin.js
deleted file mode 100644 (file)
index 7d21e02..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// This file is a modified version of:
-// https://cs.chromium.org/chromium/src/v8/tools/SourceMap.js?rcl=dd10454c1d
-// from the V8 codebase. Logic specific to WebInspector is removed and linting
-// is made to match the Node.js style guide.
-
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This is a copy from blink dev tools, see:
-// http://src.chromium.org/viewvc/blink/trunk/Source/devtools/front_end/SourceMap.js
-// revision: 153407
-
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-'use strict';
-
-const {
-  ArrayIsArray
-} = primordials;
-
-const {
-  ERR_INVALID_ARG_TYPE
-} = require('internal/errors').codes;
-
-let base64Map;
-
-const VLQ_BASE_SHIFT = 5;
-const VLQ_BASE_MASK = (1 << 5) - 1;
-const VLQ_CONTINUATION_MASK = 1 << 5;
-
-class StringCharIterator {
-  /**
-   * @constructor
-   * @param {string} string
-   */
-  constructor(string) {
-    this._string = string;
-    this._position = 0;
-  }
-
-  /**
-   * @return {string}
-   */
-  next() {
-    return this._string.charAt(this._position++);
-  }
-
-  /**
-   * @return {string}
-   */
-  peek() {
-    return this._string.charAt(this._position);
-  }
-
-  /**
-   * @return {boolean}
-   */
-  hasNext() {
-    return this._position < this._string.length;
-  }
-}
-
-/**
- * Implements Source Map V3 model.
- * See https://github.com/google/closure-compiler/wiki/Source-Maps
- * for format description.
- * @constructor
- * @param {string} sourceMappingURL
- * @param {SourceMapV3} payload
- */
-class SourceMap {
-  #payload;
-  #mappings = [];
-  #sources = {};
-  #sourceContentByURL = {};
-
-  /**
-   * @constructor
-   * @param {SourceMapV3} payload
-   */
-  constructor(payload) {
-    if (!base64Map) {
-      const base64Digits =
-             'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-      base64Map = {};
-      for (let i = 0; i < base64Digits.length; ++i)
-        base64Map[base64Digits[i]] = i;
-    }
-    this.#payload = cloneSourceMapV3(payload);
-    this.#parseMappingPayload();
-  }
-
-  /**
-   * @return {Object} raw source map v3 payload.
-   */
-  get payload() {
-    return cloneSourceMapV3(this.#payload);
-  }
-
-  /**
-   * @param {SourceMapV3} mappingPayload
-   */
-  #parseMappingPayload = () => {
-    if (this.#payload.sections) {
-      this.#parseSections(this.#payload.sections);
-    } else {
-      this.#parseMap(this.#payload, 0, 0);
-    }
-    this.#mappings.sort(compareSourceMapEntry);
-  }
-
-  /**
-   * @param {Array.<SourceMapV3.Section>} sections
-   */
-  #parseSections = (sections) => {
-    for (let i = 0; i < sections.length; ++i) {
-      const section = sections[i];
-      this.#parseMap(section.map, section.offset.line, section.offset.column);
-    }
-  }
-
-  /**
-   * @param {number} lineNumber in compiled resource
-   * @param {number} columnNumber in compiled resource
-   * @return {?Array}
-   */
-  findEntry(lineNumber, columnNumber) {
-    let first = 0;
-    let count = this.#mappings.length;
-    while (count > 1) {
-      const step = count >> 1;
-      const middle = first + step;
-      const mapping = this.#mappings[middle];
-      if (lineNumber < mapping[0] ||
-          (lineNumber === mapping[0] && columnNumber < mapping[1])) {
-        count = step;
-      } else {
-        first = middle;
-        count -= step;
-      }
-    }
-    const entry = this.#mappings[first];
-    if (!first && entry && (lineNumber < entry[0] ||
-        (lineNumber === entry[0] && columnNumber < entry[1]))) {
-      return {};
-    } else if (!entry) {
-      return {};
-    }
-    return {
-      generatedLine: entry[0],
-      generatedColumn: entry[1],
-      originalSource: entry[2],
-      originalLine: entry[3],
-      originalColumn: entry[4]
-    };
-  }
-
-  /**
-   * @override
-   */
-  #parseMap = (map, lineNumber, columnNumber) => {
-    let sourceIndex = 0;
-    let sourceLineNumber = 0;
-    let sourceColumnNumber = 0;
-
-    const sources = [];
-    const originalToCanonicalURLMap = {};
-    for (let i = 0; i < map.sources.length; ++i) {
-      const url = map.sources[i];
-      originalToCanonicalURLMap[url] = url;
-      sources.push(url);
-      this.#sources[url] = true;
-
-      if (map.sourcesContent && map.sourcesContent[i])
-        this.#sourceContentByURL[url] = map.sourcesContent[i];
-    }
-
-    const stringCharIterator = new StringCharIterator(map.mappings);
-    let sourceURL = sources[sourceIndex];
-
-    while (true) {
-      if (stringCharIterator.peek() === ',')
-        stringCharIterator.next();
-      else {
-        while (stringCharIterator.peek() === ';') {
-          lineNumber += 1;
-          columnNumber = 0;
-          stringCharIterator.next();
-        }
-        if (!stringCharIterator.hasNext())
-          break;
-      }
-
-      columnNumber += decodeVLQ(stringCharIterator);
-      if (isSeparator(stringCharIterator.peek())) {
-        this.#mappings.push([lineNumber, columnNumber]);
-        continue;
-      }
-
-      const sourceIndexDelta = decodeVLQ(stringCharIterator);
-      if (sourceIndexDelta) {
-        sourceIndex += sourceIndexDelta;
-        sourceURL = sources[sourceIndex];
-      }
-      sourceLineNumber += decodeVLQ(stringCharIterator);
-      sourceColumnNumber += decodeVLQ(stringCharIterator);
-      if (!isSeparator(stringCharIterator.peek()))
-        // Unused index into the names list.
-        decodeVLQ(stringCharIterator);
-
-      this.#mappings.push([lineNumber, columnNumber, sourceURL,
-                           sourceLineNumber, sourceColumnNumber]);
-    }
-  };
-}
-
-/**
- * @param {string} char
- * @return {boolean}
- */
-function isSeparator(char) {
-  return char === ',' || char === ';';
-}
-
-/**
- * @param {SourceMap.StringCharIterator} stringCharIterator
- * @return {number}
- */
-function decodeVLQ(stringCharIterator) {
-  // Read unsigned value.
-  let result = 0;
-  let shift = 0;
-  let digit;
-  do {
-    digit = base64Map[stringCharIterator.next()];
-    result += (digit & VLQ_BASE_MASK) << shift;
-    shift += VLQ_BASE_SHIFT;
-  } while (digit & VLQ_CONTINUATION_MASK);
-
-  // Fix the sign.
-  const negative = result & 1;
-  // Use unsigned right shift, so that the 32nd bit is properly shifted to the
-  // 31st, and the 32nd becomes unset.
-  result >>>= 1;
-  if (!negative) {
-    return result;
-  }
-
-  // We need to OR here to ensure the 32nd bit (the sign bit in an Int32) is
-  // always set for negative numbers. If `result` were 1, (meaning `negate` is
-  // true and all other bits were zeros), `result` would now be 0. But -0
-  // doesn't flip the 32nd bit as intended. All other numbers will successfully
-  // set the 32nd bit without issue, so doing this is a noop for them.
-  return -result | (1 << 31);
-}
-
-/**
- * @param {SourceMapV3} payload
- * @return {SourceMapV3}
- */
-function cloneSourceMapV3(payload) {
-  if (typeof payload !== 'object') {
-    throw new ERR_INVALID_ARG_TYPE('payload', ['Object'], payload);
-  }
-  payload = { ...payload };
-  for (const key in payload) {
-    if (payload.hasOwnProperty(key) && ArrayIsArray(payload[key])) {
-      payload[key] = payload[key].slice(0);
-    }
-  }
-  return payload;
-}
-
-/**
- * @param {Array} entry1 source map entry [lineNumber, columnNumber, sourceURL,
- *  sourceLineNumber, sourceColumnNumber]
- * @param {Array} entry2 source map entry.
- * @return {number}
- */
-function compareSourceMapEntry(entry1, entry2) {
-  const [lineNumber1, columnNumber1] = entry1;
-  const [lineNumber2, columnNumber2] = entry2;
-  if (lineNumber1 !== lineNumber2) {
-    return lineNumber1 - lineNumber2;
-  }
-  return columnNumber1 - columnNumber2;
-}
-
-module.exports = {
-  SourceMap
-};
index cda645fca32dbd69d676bfe4cec81db44c3d36b8..c10433a36f6dcb43f3ba21a8744d2802b2122fac 100644 (file)
@@ -254,8 +254,8 @@ const kDependencySpecifiers = Symbol('kDependencySpecifiers');
 const kNoError = Symbol('kNoError');
 
 class SourceTextModule extends Module {
-  error = kNoError; // @lwnode (module.origin.js)
-  statusOverride;   // @lwnode (module.origin.js)
+  #error = kNoError;
+  #statusOverride;
 
   constructor(sourceText, options = {}) {
     validateString(sourceText, 'sourceText');
@@ -310,7 +310,7 @@ class SourceTextModule extends Module {
     });
 
     this[kLink] = async (linker) => {
-      this.statusOverride = 'linking';
+      this.#statusOverride = 'linking';
 
       const promises = this[kWrap].link(async (identifier) => {
         const module = await linker(identifier, this);
@@ -334,10 +334,10 @@ class SourceTextModule extends Module {
           await SafePromise.all(promises);
         }
       } catch (e) {
-        this.error = e;
+        this.#error = e;
         throw e;
       } finally {
-        this.statusOverride = undefined;
+        this.#statusOverride = undefined;
       }
     };
 
@@ -358,11 +358,11 @@ class SourceTextModule extends Module {
     if (this[kWrap] === undefined) {
       throw new ERR_VM_MODULE_NOT_MODULE();
     }
-    if (this.error !== kNoError) {
+    if (this.#error !== kNoError) {
       return 'errored';
     }
-    if (this.statusOverride) {
-      return this.statusOverride;
+    if (this.#statusOverride) {
+      return this.#statusOverride;
     }
     return super.status;
   }
@@ -371,8 +371,8 @@ class SourceTextModule extends Module {
     if (this[kWrap] === undefined) {
       throw new ERR_VM_MODULE_NOT_MODULE();
     }
-    if (this.error !== kNoError) {
-      return this.error;
+    if (this.#error !== kNoError) {
+      return this.#error;
     }
     return super.error;
   }
diff --git a/lib/internal/vm/module.origin.js b/lib/internal/vm/module.origin.js
deleted file mode 100644 (file)
index c10433a..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-'use strict';
-
-const assert = require('internal/assert');
-const {
-  ArrayIsArray,
-  ObjectCreate,
-  ObjectDefineProperty,
-  ObjectGetPrototypeOf,
-  ObjectSetPrototypeOf,
-  SafePromise,
-  Symbol,
-  TypeError,
-  WeakMap,
-} = primordials;
-
-const { isContext } = internalBinding('contextify');
-const {
-  isModuleNamespaceObject,
-  isArrayBufferView,
-} = require('internal/util/types');
-const {
-  getConstructorOf,
-  customInspectSymbol,
-  emitExperimentalWarning,
-} = require('internal/util');
-const {
-  ERR_INVALID_ARG_TYPE,
-  ERR_INVALID_ARG_VALUE,
-  ERR_VM_MODULE_ALREADY_LINKED,
-  ERR_VM_MODULE_DIFFERENT_CONTEXT,
-  ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA,
-  ERR_VM_MODULE_LINKING_ERRORED,
-  ERR_VM_MODULE_NOT_MODULE,
-  ERR_VM_MODULE_STATUS,
-} = require('internal/errors').codes;
-const {
-  validateInt32,
-  validateUint32,
-  validateString,
-} = require('internal/validators');
-
-const binding = internalBinding('module_wrap');
-const {
-  ModuleWrap,
-  kUninstantiated,
-  kInstantiating,
-  kInstantiated,
-  kEvaluating,
-  kEvaluated,
-  kErrored,
-} = binding;
-
-const STATUS_MAP = {
-  [kUninstantiated]: 'unlinked',
-  [kInstantiating]: 'linking',
-  [kInstantiated]: 'linked',
-  [kEvaluating]: 'evaluating',
-  [kEvaluated]: 'evaluated',
-  [kErrored]: 'errored',
-};
-
-let globalModuleId = 0;
-const defaultModuleName = 'vm:module';
-const wrapToModuleMap = new WeakMap();
-
-const kWrap = Symbol('kWrap');
-const kContext = Symbol('kContext');
-const kPerContextModuleId = Symbol('kPerContextModuleId');
-const kLink = Symbol('kLink');
-
-class Module {
-  constructor(options) {
-    emitExperimentalWarning('VM Modules');
-
-    if (new.target === Module) {
-      // eslint-disable-next-line no-restricted-syntax
-      throw new TypeError('Module is not a constructor');
-    }
-
-    const {
-      context,
-      sourceText,
-      syntheticExportNames,
-      syntheticEvaluationSteps,
-    } = options;
-
-    if (context !== undefined) {
-      if (typeof context !== 'object' || context === null) {
-        throw new ERR_INVALID_ARG_TYPE('options.context', 'Object', context);
-      }
-      if (!isContext(context)) {
-        throw new ERR_INVALID_ARG_TYPE('options.context', 'vm.Context',
-                                       context);
-      }
-    }
-
-    let { identifier } = options;
-    if (identifier !== undefined) {
-      validateString(identifier, 'options.identifier');
-    } else if (context === undefined) {
-      identifier = `${defaultModuleName}(${globalModuleId++})`;
-    } else if (context[kPerContextModuleId] !== undefined) {
-      const curId = context[kPerContextModuleId];
-      identifier = `${defaultModuleName}(${curId})`;
-      context[kPerContextModuleId] += 1;
-    } else {
-      identifier = `${defaultModuleName}(0)`;
-      ObjectDefineProperty(context, kPerContextModuleId, {
-        value: 1,
-        writable: true,
-        enumerable: false,
-        configurable: true,
-      });
-    }
-
-    if (sourceText !== undefined) {
-      this[kWrap] = new ModuleWrap(identifier, context, sourceText,
-                                   options.lineOffset, options.columnOffset,
-                                   options.cachedData);
-
-      binding.callbackMap.set(this[kWrap], {
-        initializeImportMeta: options.initializeImportMeta,
-        importModuleDynamically: options.importModuleDynamically ?
-          importModuleDynamicallyWrap(options.importModuleDynamically) :
-          undefined,
-      });
-    } else {
-      assert(syntheticEvaluationSteps);
-      this[kWrap] = new ModuleWrap(identifier, context,
-                                   syntheticExportNames,
-                                   syntheticEvaluationSteps);
-    }
-
-    wrapToModuleMap.set(this[kWrap], this);
-
-    this[kContext] = context;
-  }
-
-  get identifier() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    return this[kWrap].url;
-  }
-
-  get context() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    return this[kContext];
-  }
-
-  get namespace() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (this[kWrap].getStatus() < kInstantiated) {
-      throw new ERR_VM_MODULE_STATUS('must not be unlinked or linking');
-    }
-    return this[kWrap].getNamespace();
-  }
-
-  get status() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    return STATUS_MAP[this[kWrap].getStatus()];
-  }
-
-  get error() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (this[kWrap].getStatus() !== kErrored) {
-      throw new ERR_VM_MODULE_STATUS('must be errored');
-    }
-    return this[kWrap].getError();
-  }
-
-  async link(linker) {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (typeof linker !== 'function') {
-      throw new ERR_INVALID_ARG_TYPE('linker', 'function', linker);
-    }
-    if (this.status === 'linked') {
-      throw new ERR_VM_MODULE_ALREADY_LINKED();
-    }
-    if (this.status !== 'unlinked') {
-      throw new ERR_VM_MODULE_STATUS('must be unlinked');
-    }
-    await this[kLink](linker);
-    this[kWrap].instantiate();
-  }
-
-  async evaluate(options = {}) {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-
-    if (typeof options !== 'object' || options === null) {
-      throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
-    }
-
-    let timeout = options.timeout;
-    if (timeout === undefined) {
-      timeout = -1;
-    } else {
-      validateUint32(timeout, 'options.timeout', true);
-    }
-    const { breakOnSigint = false } = options;
-    if (typeof breakOnSigint !== 'boolean') {
-      throw new ERR_INVALID_ARG_TYPE('options.breakOnSigint', 'boolean',
-                                     breakOnSigint);
-    }
-    const status = this[kWrap].getStatus();
-    if (status !== kInstantiated &&
-        status !== kEvaluated &&
-        status !== kErrored) {
-      throw new ERR_VM_MODULE_STATUS(
-        'must be one of linked, evaluated, or errored'
-      );
-    }
-    await this[kWrap].evaluate(timeout, breakOnSigint);
-  }
-
-  [customInspectSymbol](depth, options) {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (typeof depth === 'number' && depth < 0)
-      return this;
-
-    const constructor = getConstructorOf(this) || Module;
-    const o = ObjectCreate({ constructor });
-    o.status = this.status;
-    o.identifier = this.identifier;
-    o.context = this.context;
-
-    ObjectSetPrototypeOf(o, ObjectGetPrototypeOf(this));
-    ObjectDefineProperty(o, Symbol.toStringTag, {
-      value: constructor.name,
-      configurable: true
-    });
-
-    // Lazy to avoid circular dependency
-    const { inspect } = require('internal/util/inspect');
-    return inspect(o, { ...options, customInspect: false });
-  }
-}
-
-const kDependencySpecifiers = Symbol('kDependencySpecifiers');
-const kNoError = Symbol('kNoError');
-
-class SourceTextModule extends Module {
-  #error = kNoError;
-  #statusOverride;
-
-  constructor(sourceText, options = {}) {
-    validateString(sourceText, 'sourceText');
-
-    if (typeof options !== 'object' || options === null) {
-      throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
-    }
-
-    const {
-      lineOffset = 0,
-      columnOffset = 0,
-      initializeImportMeta,
-      importModuleDynamically,
-      context,
-      identifier,
-      cachedData,
-    } = options;
-
-    validateInt32(lineOffset, 'options.lineOffset');
-    validateInt32(columnOffset, 'options.columnOffset');
-
-    if (initializeImportMeta !== undefined &&
-        typeof initializeImportMeta !== 'function') {
-      throw new ERR_INVALID_ARG_TYPE(
-        'options.initializeImportMeta', 'function', initializeImportMeta);
-    }
-
-    if (importModuleDynamically !== undefined &&
-        typeof importModuleDynamically !== 'function') {
-      throw new ERR_INVALID_ARG_TYPE(
-        'options.importModuleDynamically', 'function',
-        importModuleDynamically);
-    }
-
-    if (cachedData !== undefined && !isArrayBufferView(cachedData)) {
-      throw new ERR_INVALID_ARG_TYPE(
-        'options.cachedData',
-        ['Buffer', 'TypedArray', 'DataView'],
-        cachedData
-      );
-    }
-
-    super({
-      sourceText,
-      context,
-      identifier,
-      lineOffset,
-      columnOffset,
-      cachedData,
-      initializeImportMeta,
-      importModuleDynamically,
-    });
-
-    this[kLink] = async (linker) => {
-      this.#statusOverride = 'linking';
-
-      const promises = this[kWrap].link(async (identifier) => {
-        const module = await linker(identifier, this);
-        if (module[kWrap] === undefined) {
-          throw new ERR_VM_MODULE_NOT_MODULE();
-        }
-        if (module.context !== this.context) {
-          throw new ERR_VM_MODULE_DIFFERENT_CONTEXT();
-        }
-        if (module.status === 'errored') {
-          throw new ERR_VM_MODULE_LINKING_ERRORED();
-        }
-        if (module.status === 'unlinked') {
-          await module[kLink](linker);
-        }
-        return module[kWrap];
-      });
-
-      try {
-        if (promises !== undefined) {
-          await SafePromise.all(promises);
-        }
-      } catch (e) {
-        this.#error = e;
-        throw e;
-      } finally {
-        this.#statusOverride = undefined;
-      }
-    };
-
-    this[kDependencySpecifiers] = undefined;
-  }
-
-  get dependencySpecifiers() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (this[kDependencySpecifiers] === undefined) {
-      this[kDependencySpecifiers] = this[kWrap].getStaticDependencySpecifiers();
-    }
-    return this[kDependencySpecifiers];
-  }
-
-  get status() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (this.#error !== kNoError) {
-      return 'errored';
-    }
-    if (this.#statusOverride) {
-      return this.#statusOverride;
-    }
-    return super.status;
-  }
-
-  get error() {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (this.#error !== kNoError) {
-      return this.#error;
-    }
-    return super.error;
-  }
-
-  createCachedData() {
-    const { status } = this;
-    if (status === 'evaluating' ||
-        status === 'evaluated' ||
-        status === 'errored') {
-      throw new ERR_VM_MODULE_CANNOT_CREATE_CACHED_DATA();
-    }
-    return this[kWrap].createCachedData();
-  }
-}
-
-class SyntheticModule extends Module {
-  constructor(exportNames, evaluateCallback, options = {}) {
-    if (!ArrayIsArray(exportNames) ||
-      exportNames.some((e) => typeof e !== 'string')) {
-      throw new ERR_INVALID_ARG_TYPE('exportNames',
-                                     'Array of unique strings',
-                                     exportNames);
-    } else {
-      exportNames.forEach((name, i) => {
-        if (exportNames.indexOf(name, i + 1) !== -1) {
-          throw new ERR_INVALID_ARG_VALUE(`exportNames.${name}`,
-                                          name,
-                                          'is duplicated');
-        }
-      });
-    }
-    if (typeof evaluateCallback !== 'function') {
-      throw new ERR_INVALID_ARG_TYPE('evaluateCallback', 'function',
-                                     evaluateCallback);
-    }
-
-    if (typeof options !== 'object' || options === null) {
-      throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
-    }
-
-    const { context, identifier } = options;
-
-    super({
-      syntheticExportNames: exportNames,
-      syntheticEvaluationSteps: evaluateCallback,
-      context,
-      identifier,
-    });
-
-    this[kLink] = () => this[kWrap].link(() => {
-      assert.fail('link callback should not be called');
-    });
-  }
-
-  setExport(name, value) {
-    if (this[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    validateString(name, 'name');
-    if (this[kWrap].getStatus() < kInstantiated) {
-      throw new ERR_VM_MODULE_STATUS('must be linked');
-    }
-    this[kWrap].setExport(name, value);
-  }
-}
-
-function importModuleDynamicallyWrap(importModuleDynamically) {
-  const importModuleDynamicallyWrapper = async (...args) => {
-    const m = await importModuleDynamically(...args);
-    if (isModuleNamespaceObject(m)) {
-      return m;
-    }
-    if (!m || m[kWrap] === undefined) {
-      throw new ERR_VM_MODULE_NOT_MODULE();
-    }
-    if (m.status === 'errored') {
-      throw m.error;
-    }
-    return m.namespace;
-  };
-  return importModuleDynamicallyWrapper;
-}
-
-module.exports = {
-  Module,
-  SourceTextModule,
-  SyntheticModule,
-  importModuleDynamicallyWrap,
-  getModuleFromWrap: (wrap) => wrapToModuleMap.get(wrap),
-};
index f1721cba2db4877b7201352b7ca03f4bef6abdbf..3d197ad2ec5358cff7b144d1d681d6c79661a294 100644 (file)
@@ -633,7 +633,6 @@ function REPLServer(prompt,
       // @lwnode
       // const lines = errStack.split(/(?<=\n)/);
       const lines = errStack.split(/^/m);
-
       let matched = false;
 
       errStack = '';
index 45a2edf0bb20b3a3ab8121daa3f98f8e8ffc6601..ce02c8617ef36f30e09c650608ae846e4e250db5 100644 (file)
--- a/lib/vm.js
+++ b/lib/vm.js
@@ -139,7 +139,15 @@ class Script extends ContextifyScript {
       return sigintHandlersWrap(super.runInContext, this,
                                 [contextifiedObject, ...args]);
     }
-    return super.runInContext(contextifiedObject, ...args);
+
+    // @lwnode: Due to the incorrect Escargot execution,
+    // we split the code into two.
+    // @before
+    // return super.runInContext(contextifiedObject, ...args);
+    // @after
+    var r = super.runInContext(contextifiedObject, ...args);
+    return r;
+    // @end of lwnode
   }
 
   runInNewContext(contextObject, options) {
diff --git a/lwnode/build-cctest-node.sh b/lwnode/build-cctest-node.sh
new file mode 100755 (executable)
index 0000000..1a77e98
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Copyright (c) 2021-present Samsung Electronics Co., Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CONFIG="--without-npm --without-bundled-v8 \
+    --without-inspector --without-node-code-cache --without-node-snapshot \
+    --with-intl none --shared-openssl --shared-zlib \
+    --dest-os linux --dest-cpu x64 \
+    --engine escargot \
+    --ninja"
+
+if [[ $1 =~ ^"-d" ]]; then
+  ! [[ $1 =~ .*"b" ]] && ./configure $CONFIG --debug --debug-node
+  ninja -v -C out/Debug cctest |& lwnode/tools/colorize.sh
+
+else
+  ./configure $CONFIG
+  ninja -v -C out/Release cctest |& lwnode/tools/colorize.sh
+fi
index a13977e69eee0fb54647aad2e186bdd17015f690..5ab8701bf6b1833e5d8cf9f56a8fd7fc0a6889f6 100755 (executable)
@@ -17,7 +17,8 @@ ROOT_PATH=out/cctest
 
 ./tools/gyp/gyp ./lwnode/code/escargotshim/test/cctest.gyp --depth=. -f ninja \
   --generator-output=$ROOT_PATH -Dbuild_asan=1 -Dbuild_mode=debug \
-  -Descargot_lib_type=static_lib -Denable_experimental=true -Dtarget_arch=x64
+  -Descargot_lib_type=static_lib -Dtarget_arch=x64 -Dtarget_os=linux \
+  -Denable_experimental=true -Descargot_threading=1
 
 ninja -v -C $ROOT_PATH/out/Debug cctest
 
index c4d8dd469addaa600e1ae30faeefdda7951eb7f9..5b6686dff4acc45d71f3e376633e58635b3439ed 100755 (executable)
@@ -20,14 +20,14 @@ CONFIG="--without-npm --without-bundled-v8 \
     --without-inspector --without-node-code-cache --without-node-snapshot \
     --with-intl none --shared-openssl --shared-zlib \
     --dest-os linux --dest-cpu x64 \
-    --engine escargot \
+    --engine escargot --escargot-threading \
     --ninja"
 
 if [[ $1 =~ ^"-d" ]]; then
   ! [[ $1 =~ .*"b" ]] && ./configure $CONFIG --debug --debug-node
-  ninja -v -C out/Debug lwnode |& lwnode/tools/colorize.sh
+  ninja -v -C out/linux/Debug lwnode |& lwnode/tools/colorize.sh
 
 else
   ./configure $CONFIG
-  ninja -v -C out/Release lwnode |& lwnode/tools/colorize.sh
+  ninja -v -C out/linux/Release lwnode |& lwnode/tools/colorize.sh
 fi
index b83ea338b38e5c7364c42e4a28a75cb91cbce6ae..5a939814201b4e3066bf8e761a1960ecf7390ceb 100755 (executable)
     'defines': [ 'LWNODE=1' ],
     'cflags!': [ '-Wno-error' ],
     'cflags': [
-      '-Wall', '-Wextra', '-Werror', '-ggdb',
+      '-Wall', '-Wextra', '-Werror',
       '-Wno-unused-variable',
       '-Wno-unused-function',
       '-Wno-unused-but-set-variable',
+      '-fPIC',
+      '-ggdb', # all builds include debug symbols, which will be stripped before packaging
     ],
     'link_settings': {
       'libraries': [ '-ldl', '-lrt' ],
     'conditions': [
       ['target_os=="tizen"', {
         'target_defaults': {
-          'defines': [
-            'HOST_TIZEN',
+          'defines': ['HOST_TIZEN'],
+          'cflags': [
+            '-Os',
+            '-fPIE',
+            '-fstack-protector-strong',
+            '-D_FORTIFY_SOURCE=2',
           ],
           'ldflags': [
-            '-mthumb',
             '-pie',
             '-Wl,-z,relro,-z,now',
           ],
-          'cflags': [
-            '-ggdb', '-Os',
-            '-fPIC', '-fPIE',
-            '-fstack-protector-strong',
-            '-D_FORTIFY_SOURCE=2',
-          ],
         },
       }],
       ['build_asan==1', {
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_android_arm.cmake
deleted file mode 100644 (file)
index ee682ed..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_DEFINITIONS -DANDROID=1 -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-SET (ESCARGOT_HOST android)
-SET (ESCARGOT_ARCH arm)
-SET (ESCARGOT_LDFLAGS -fPIE -pie -march=armv7-a -Wl,--fix-cortex-a8 -llog -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_darwin_x64.cmake
deleted file mode 100644 (file)
index c004e44..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -Wl,-dead_strip)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_aarch64.cmake
deleted file mode 100644 (file)
index e225b9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_arm.cmake
deleted file mode 100644 (file)
index 25ff1e3..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti -march=armv7-a -mthumb)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_i686.cmake
deleted file mode 100644 (file)
index 2f0543b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x64.cmake
deleted file mode 100644 (file)
index e225b9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_linux_x86.cmake
deleted file mode 100644 (file)
index bddf67f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -m32)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_aarch64.cmake
deleted file mode 100644 (file)
index e225b9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_arm.cmake
deleted file mode 100644 (file)
index 0f07369..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (GC_CONFIGURE_HOST)
-
-SET (ESCARGOT_CXXFLAGS)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_TIZEN -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -O1)
-SET (ESCARGOT_CXXFLAGS_RELEASE -O2)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_i686.cmake
deleted file mode 100644 (file)
index d6e8c89..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (GC_CONFIGURE_HOST)
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x64.cmake
deleted file mode 100644 (file)
index e225b9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86.cmake
deleted file mode 100644 (file)
index bddf67f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti -m32 -mfpmath=sse -msse -msse2)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_32=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG)
-SET (ESCARGOT_CXXFLAGS_RELEASE)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections -m32)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -m32)
diff --git a/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake b/lwnode/code/escargotshim/deps/escargot/build/cmake/toolchain_tizen_obs_x86_64.cmake
deleted file mode 100644 (file)
index e225b9e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2019-present Samsung Electronics Co., Ltd
-#
-#  This library is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU Lesser General Public
-#  License as published by the Free Software Foundation; either
-#  version 2.1 of the License, or (at your option) any later version.
-#
-#  This library is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  Lesser General Public License for more details.
-#
-#  You should have received a copy of the GNU Lesser General Public
-#  License along with this library; if not, write to the Free Software
-#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
-#  USA
-
-SET (ESCARGOT_CXXFLAGS -fno-rtti)
-
-SET (ESCARGOT_DEFINITIONS -DESCARGOT_64=1)
-
-SET (ESCARGOT_CXXFLAGS_DEBUG -DESCARGOT_USE_32BIT_IN_64BIT)
-SET (ESCARGOT_CXXFLAGS_RELEASE -DESCARGOT_USE_32BIT_IN_64BIT)
-
-SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
-
-SET (ESCARGOT_LIBRARIES)
-SET (ESCARGOT_INCDIRS)
-
-SET (ESCARGOT_GCUTIL_CFLAGS -DESCARGOT_USE_32BIT_IN_64BIT)
index cc0d4c8430280b936db4fee224346c1d21b69628..20304254e6b755a98dbc9617ab3659dfd651a32d 100644 (file)
@@ -3,12 +3,6 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
 #######################################################
 # CONFIGURATION
 #######################################################
-IF (EXISTS "${PROJECT_SOURCE_DIR}/build/cmake/toolchain_${ESCARGOT_HOST}_${ESCARGOT_ARCH}.cmake")
-    INCLUDE ("${PROJECT_SOURCE_DIR}/build/cmake/toolchain_${ESCARGOT_HOST}_${ESCARGOT_ARCH}.cmake")
-ELSE()
-    MESSAGE (FATAL_ERROR "Error: unsupported target")
-ENDIF()
-
 # CONFIGURE ESCARGOT VERSION
 FIND_PACKAGE(Git)
 IF (GIT_FOUND)
@@ -32,6 +26,10 @@ SET (ESCARGOT_ROOT ${PROJECT_SOURCE_DIR})
 SET (ESCARGOT_THIRD_PARTY_ROOT ${ESCARGOT_ROOT}/third_party)
 SET (GCUTIL_ROOT ${ESCARGOT_THIRD_PARTY_ROOT}/GCutil)
 
+#######################################################
+# FLAGS FOR TARGET
+#######################################################
+INCLUDE (${ESCARGOT_ROOT}/build/target.cmake)
 
 #######################################################
 # FLAGS FOR COMMON
@@ -85,17 +83,11 @@ ELSE()
     MESSAGE (FATAL_ERROR ${CMAKE_CXX_COMPILER_ID} " is Unsupported Compiler")
 ENDIF()
 
-
-
 # bdwgc
 IF (${ESCARGOT_MODE} STREQUAL "debug")
     SET (ESCARGOT_DEFINITIONS_COMMON ${ESCARGOT_DEFINITIONS_COMMON} -DGC_DEBUG)
 ENDIF()
 
-#######################################################
-# FLAGS FOR $(ESCARGOT_HOST)
-#######################################################
-
 IF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib" AND ${ESCARGOT_HOST} STREQUAL "android")
     SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -shared)
 ENDIF()
@@ -112,7 +104,6 @@ IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
     SET (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN ON)
 ENDIF()
 
-
 IF (${ESCARGOT_HOST} STREQUAL "android")
     SET (ESCARGOT_LIBICU_SUPPORT OFF)
 ENDIF()
@@ -120,7 +111,8 @@ ENDIF()
 #######################################################
 # FLAGS FOR ADDITIONAL FUNCTION
 #######################################################
-
+SET (ESCARGOT_LIBRARIES)
+SET (ESCARGOT_INCDIRS)
 FIND_PACKAGE (PkgConfig REQUIRED)
 IF (ESCARGOT_LIBICU_SUPPORT)
     IF (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
@@ -170,23 +162,20 @@ IF (ESCARGOT_THREADING)
 ENDIF()
 
 #######################################################
-# flags for $(MODE) : debug/release
+# FLAGS FOR $(MODE) : debug/release
 #######################################################
 # DEBUG FLAGS
 SET (ESCARGOT_CXXFLAGS_DEBUG -O0 -Wall -Wextra -Werror ${ESCARGOT_CXXFLAGS_DEBUG})
 SET (ESCARGOT_DEFINITIONS_DEBUG -D_GLIBCXX_DEBUG -DGC_DEBUG)
 
-
 # RELEASE FLAGS
 SET (ESCARGOT_CXXFLAGS_RELEASE -O2 -fno-stack-protector ${ESCARGOT_CXXFLAGS_RELEASE})
 SET (ESCARGOT_DEFINITIONS_RELEASE -DNDEBUG)
 
-
 # SHARED_LIB FLAGS
 SET (ESCARGOT_CXXFLAGS_SHAREDLIB -fPIC)
 SET (ESCARGOT_LDFLAGS_SHAREDLIB -ldl)
 
-
 # STATIC_LIB FLAGS
 SET (ESCARGOT_CXXFLAGS_STATICLIB -fPIC -DESCARGOT_EXPORT=)
 SET (ESCARGOT_LDFLAGS_STATICLIB -Wl,--gc-sections)
@@ -195,13 +184,11 @@ SET (ESCARGOT_LDFLAGS_STATICLIB -Wl,--gc-sections)
 SET (ESCARGOT_CXXFLAGS_SHELL -DESCARGOT_EXPORT=)
 SET (ESCARGOT_LDFLAGS_SHELL -Wl,--gc-sections)
 
-
 #######################################################
 # FLAGS FOR TEST
 #######################################################
 SET (ESCARGOT_DEFINITIONS_TEST -DESCARGOT_ENABLE_TEST)
 
-
 #######################################################
 # FLAGS FOR MEMORY PROFILING
 #######################################################
@@ -223,7 +210,6 @@ ENDIF()
 # FLAGS FOR DEBUGGER
 #######################################################
 SET (DEBUGGER_FLAGS)
-
 IF (ESCARGOT_DEBUGGER)
     SET (DEBUGGER_FLAGS ${DEBUGGER_FLAGS} -DESCARGOT_DEBUGGER)
 ENDIF()
index e19f32ec485f56d0a5e08f64120116faa7744e33..5359820e1f25d54b12ddbf10a2a68b47c779f122 100644 (file)
@@ -72,12 +72,12 @@ SET (ESCARGOT_SRC_LIST
 
 # GCUTIL
 IF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib")
-    SET (ESCARGOT_GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS} ${ESCARGOT_CXXFLAGS_SHAREDLIB})
+    SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} ${ESCARGOT_CXXFLAGS_SHAREDLIB})
 ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "static_lib")
-    SET (ESCARGOT_GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS} ${ESCARGOT_CXXFLAGS_STATICLIB})
+    SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} ${ESCARGOT_CXXFLAGS_STATICLIB})
 ENDIF()
 
-SET (GCUTIL_CFLAGS ${ESCARGOT_GCUTIL_CFLAGS})
+SET (GCUTIL_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS})
 
 IF (ESCARGOT_SMALL_CONFIG)
     SET (GCUTIL_CFLAGS ${GCUTIL_CFLAGS} -DSMALL_CONFIG -DMAX_HEAP_SECTS=512)
@@ -98,7 +98,7 @@ ADD_LIBRARY (libbf STATIC
     ${ESCARGOT_THIRD_PARTY_ROOT}/libbf/cutils.c)
 TARGET_INCLUDE_DIRECTORIES (libbf PUBLIC ${ESCARGOT_THIRD_PARTY_ROOT}/libbf)
 SET (LIBBF_CFLAGS
-       ${ESCARGOT_GCUTIL_CFLAGS} # we can share arch flags with gcutil
+       ${ESCARGOT_THIRDPARTY_CFLAGS} # we can share flags with gcutil
        ${CFLAGS_FROM_ENV}
     -w
     -g3
@@ -135,7 +135,7 @@ SET (ESCARGOT_LIBRARIES ${ESCARGOT_LIBRARIES} runtime-icu-binder-static)
 # WebAssembly (wabt)
 IF (ESCARGOT_WASM)
     SET (WASM_CXX_FLAGS
-           ${ESCARGOT_GCUTIL_CFLAGS} # we can share arch flags with gcutil
+           ${ESCARGOT_THIRDPARTY_CFLAGS} # we can share flags with gcutil
         -g3)
     SET (WASM_ARCH ${ESCARGOT_ARCH})
 
@@ -149,31 +149,31 @@ IF (${ESCARGOT_OUTPUT} MATCHES "shell")
     ADD_EXECUTABLE (${ESCARGOT_TARGET} ${ESCARGOT_SRC_LIST})
 
     TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV})
-    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS})
-    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS})
-    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV} ${PROFILER_FLAGS} ${DEBUGGER_FLAGS})
+    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS})
+    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS})
+    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV} ${PROFILER_FLAGS} ${DEBUGGER_FLAGS})
 
 ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "shared_lib")
     ADD_LIBRARY (${ESCARGOT_TARGET} SHARED ${ESCARGOT_SRC_LIST})
 
     TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV})
-    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS})
-    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS})
-    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV})
+    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS})
+    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS})
+    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV})
 
 ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "static_lib")
     ADD_LIBRARY (${ESCARGOT_TARGET} STATIC ${ESCARGOT_SRC_LIST})
 
     TARGET_LINK_LIBRARIES (${ESCARGOT_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV})
-    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_INCDIRS})
-    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS})
-    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV})
+    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_INCDIRS})
+    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS})
+    TARGET_COMPILE_OPTIONS (${ESCARGOT_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} ${CXXFLAGS_FROM_ENV})
 
 ELSEIF (${ESCARGOT_OUTPUT} STREQUAL "cctest")
     ADD_EXECUTABLE (${ESCARGOT_CCTEST_TARGET} ${ESCARGOT_SRC_LIST})
 
     TARGET_LINK_LIBRARIES (${ESCARGOT_CCTEST_TARGET} ${ESCARGOT_LIBRARIES} ${ESCARGOT_LDFLAGS} ${LDFLAGS_FROM_ENV} gtest)
-    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_INCDIRS})
-    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_DEFINITIONS})
-    TARGET_COMPILE_OPTIONS (${ESCARGOT_CCTEST_TARGET} PUBLIC ${ESCARGOT_CXXFLAGS} -I${ESCARGOT_ROOT}/third_party/googletest/googletest/include/ ${CXXFLAGS_FROM_ENV})
+    TARGET_INCLUDE_DIRECTORIES (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_INCDIRS})
+    TARGET_COMPILE_DEFINITIONS (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_DEFINITIONS})
+    TARGET_COMPILE_OPTIONS (${ESCARGOT_CCTEST_TARGET} PRIVATE ${ESCARGOT_CXXFLAGS} -I${ESCARGOT_ROOT}/third_party/googletest/googletest/include/ ${CXXFLAGS_FROM_ENV})
 ENDIF()
diff --git a/lwnode/code/escargotshim/deps/escargot/build/target.cmake b/lwnode/code/escargotshim/deps/escargot/build/target.cmake
new file mode 100644 (file)
index 0000000..763e1c0
--- /dev/null
@@ -0,0 +1,62 @@
+# default set of each flag
+SET (ESCARGOT_CXXFLAGS -fno-rtti) # build escargot without rtti
+SET (ESCARGOT_CXXFLAGS_DEBUG)
+SET (ESCARGOT_CXXFLAGS_RELEASE)
+SET (ESCARGOT_LDFLAGS)
+SET (ESCARGOT_DEFINITIONS)
+SET (ESCARGOT_THIRDPARTY_CFLAGS)
+
+SET (ESCARGOT_BUILD_32BIT OFF)
+
+IF (${ESCARGOT_HOST} STREQUAL "linux")
+    # default set of LDFLAGS
+    SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
+    IF (${ESCARGOT_ARCH} STREQUAL "x64")
+    ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686"))
+        SET (ESCARGOT_BUILD_32BIT ON)
+        SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2)                                                                                                                              
+        SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -m32)
+        SET (ESCARGOT_THIRDPARTY_CFLAGS -m32)
+    ELSEIF (${ESCARGOT_ARCH} STREQUAL "arm")
+        SET (ESCARGOT_BUILD_32BIT ON)
+        SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -march=armv7-a -mthumb)
+    ELSEIF (${ESCARGOT_ARCH} STREQUAL "aarch64")
+    ELSE()
+        MESSAGE (FATAL_ERROR ${ESCARGOT_ARCH} " is unsupported")
+    ENDIF()
+ELSEIF (${ESCARGOT_HOST} STREQUAL "tizen_obs")
+    # default set of LDFLAGS
+    SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
+    SET (ESCARGOT_DEFINITIONS -DESCARGOT_TIZEN)
+    IF (${ESCARGOT_ARCH} STREQUAL "x64")
+    ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686"))
+        SET (ESCARGOT_BUILD_32BIT ON)
+        SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2)
+        SET (ESCARGOT_LDFLAGS ${ESCARGOT_LDFLAGS} -m32)
+        SET (ESCARGOT_THIRDPARTY_CFLAGS -m32)
+    ELSEIF (${ESCARGOT_ARCH} STREQUAL "arm")
+        SET (ESCARGOT_BUILD_32BIT ON)
+        SET (ESCARGOT_CXXFLAGS_DEBUG -O1)
+        SET (ESCARGOT_CXXFLAGS_RELEASE -O2)
+    ELSEIF (${ESCARGOT_ARCH} STREQUAL "aarch64")
+    ELSE()
+        MESSAGE (FATAL_ERROR ${ESCARGOT_ARCH} " is unsupported")
+    ENDIF()
+ELSEIF (${ESCARGOT_HOST} STREQUAL "android" AND ${ESCARGOT_ARCH} STREQUAL "arm")
+    SET (ESCARGOT_BUILD_32BIT ON)
+    SET (ESCARGOT_LDFLAGS -fPIE -pie -march=armv7-a -Wl,--fix-cortex-a8 -llog -Wl,--gc-sections)
+    SET (ESCARGOT_DEFINITIONS -DANDROID=1)
+ELSEIF (${ESCARGOT_HOST} STREQUAL "darwin" AND ${ESCARGOT_ARCH} STREQUAL "x64")
+    SET (ESCARGOT_LDFLAGS -lpthread -Wl,-dead_strip)
+ELSE()
+    MESSAGE (FATAL_ERROR ${ESCARGOT_HOST} " with " ${ESCARGOT_ARCH} " is unsupported")
+ENDIF()
+
+IF (ESCARGOT_BUILD_32BIT)
+    # 32bit build
+    SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DESCARGOT_32=1)
+ELSE()
+    # 64bit build
+    SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DESCARGOT_64=1 -DESCARGOT_USE_32BIT_IN_64BIT)
+    SET (ESCARGOT_THIRDPARTY_CFLAGS ${ESCARGOT_THIRDPARTY_CFLAGS} -DESCARGOT_USE_32BIT_IN_64BIT)
+ENDIF()
index e8779e01fd730bf34a54e4270fb77a375449f559..d9e3db6860f8eb3097c9d499e3a86ce5af1c3904 100755 (executable)
 #define NOMINMAX
 #endif
 
+#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
+#define HAVE_BUILTIN_ATOMIC_FUNCTIONS
+#endif
 
 #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
 #define CPU_X86_64
 #include <vector>
 #include <random>
 
+#if defined(ENABLE_THREADING)
+#include <thread>
+#include <mutex>
+#include <atomic>
+#endif
+
 extern "C" {
 #include <libbf.h>
 }
 
+#ifndef ESCARGOT_BUILD_DATE
+#define ESCARGOT_BUILD_DATE __DATE__
+#endif
+
 #ifdef ENABLE_ICU
 #if defined(ENABLE_RUNTIME_ICU_BINDER)
 typedef unsigned char LChar;
index 47e31dd5b4c8ac9a0f80fdbd4c233275408070c2..0e9a964cdd59e4abe04f391091a5932a0a67a8e7 100644 (file)
 #include "parser/ast/Node.h"
 #include "parser/ScriptParser.h"
 #include "parser/CodeBlock.h"
+#include "runtime/Global.h"
+#include "runtime/ThreadLocal.h"
 #include "runtime/Context.h"
+#include "runtime/Platform.h"
 #include "runtime/FunctionObject.h"
 #include "runtime/Value.h"
 #include "runtime/VMInstance.h"
@@ -44,6 +47,7 @@
 #include "runtime/PromiseObject.h"
 #include "runtime/ProxyObject.h"
 #include "runtime/BackingStore.h"
+#include "runtime/ArrayBuffer.h"
 #include "runtime/ArrayBufferObject.h"
 #include "runtime/TypedArrayObject.h"
 #include "runtime/SetObject.h"
@@ -61,6 +65,8 @@
 #include "runtime/ExtendedNativeFunctionObject.h"
 #include "runtime/BigInt.h"
 #include "runtime/BigIntObject.h"
+#include "runtime/SharedArrayBufferObject.h"
+#include "runtime/serialization/Serializer.h"
 #include "interpreter/ByteCode.h"
 #include "api/internal/ValueAdapter.h"
 #if defined(ENABLE_WASM)
@@ -102,27 +108,190 @@ inline AtomicString toImpl(AtomicStringRef* v)
     return AtomicString::fromPayload(reinterpret_cast<void*>(v));
 }
 
+class PlatformBridge : public Platform {
+public:
+    PlatformBridge(PlatformRef* p)
+        : m_platform(p)
+    {
+    }
+
+    virtual ~PlatformBridge()
+    {
+        // delete PlatformRef, so we don't care about PlatformRef's lifetime
+        delete m_platform;
+    }
+
+    virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte) override
+    {
+        return m_platform->onMallocArrayBufferObjectDataBuffer(sizeInByte);
+    }
+
+    virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) override
+    {
+        m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte);
+    }
+
+    virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) override
+    {
+        return m_platform->onReallocArrayBufferObjectDataBuffer(oldBuffer, oldSizeInByte, newSizeInByte);
+    }
+
+    virtual void markJSJobEnqueued(Context* relatedContext) override
+    {
+        // TODO Job queue should be separately managed for each thread
+        m_platform->markJSJobEnqueued(toRef(relatedContext));
+    }
+
+    virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) override
+    {
+        LoadModuleResult result;
+        auto refResult = m_platform->onLoadModule(toRef(relatedContext), toRef(whereRequestFrom), toRef(moduleSrc));
+
+        result.script = toImpl(refResult.script.get());
+        result.errorMessage = toImpl(refResult.errorMessage);
+        result.errorCode = refResult.errorCode;
+
+        return result;
+    }
+
+    virtual void didLoadModule(Context* relatedContext, Optional<Script*> whereRequestFrom, Script* loadedModule) override
+    {
+        if (whereRequestFrom) {
+            m_platform->didLoadModule(toRef(relatedContext), toRef(whereRequestFrom.value()), toRef(loadedModule));
+        } else {
+            m_platform->didLoadModule(toRef(relatedContext), nullptr, toRef(loadedModule));
+        }
+    }
+
+    virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) override
+    {
+        m_platform->hostImportModuleDynamically(toRef(relatedContext), toRef(referrer), toRef(src), toRef(promise));
+    }
+
+    virtual void* allocateThreadLocalCustomData() override
+    {
+        return m_platform->allocateThreadLocalCustomData();
+    }
+
+    virtual void deallocateThreadLocalCustomData() override
+    {
+        m_platform->deallocateThreadLocalCustomData();
+    }
+
+private:
+    PlatformRef* m_platform;
+};
+
+void PlatformRef::notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult)
+{
+    auto result = Evaluator::execute(relatedContext, [](ExecutionStateRef* state, LoadModuleResult loadModuleResult, Script::ModuleData::ModulePromiseObject* promise) -> ValueRef* {
+        if (loadModuleResult.script) {
+            if (loadModuleResult.script.value()->isExecuted()) {
+                if (loadModuleResult.script.value()->wasThereErrorOnModuleEvaluation()) {
+                    state->throwException(loadModuleResult.script.value()->moduleEvaluationError());
+                }
+            }
+        } else {
+            state->throwException(ErrorObjectRef::create(state, loadModuleResult.errorCode, loadModuleResult.errorMessage));
+        }
+        return ValueRef::createUndefined();
+    },
+                                     loadModuleResult, (Script::ModuleData::ModulePromiseObject*)promise);
+
+    Script::ModuleData::ModulePromiseObject* mp = (Script::ModuleData::ModulePromiseObject*)promise;
+    mp->m_referrer = toImpl(referrer);
+    if (loadModuleResult.script.hasValue()) {
+        mp->m_loadedScript = toImpl(loadModuleResult.script.value());
+        if (!mp->m_loadedScript->moduleData()->m_didCallLoadedCallback) {
+            Context* ctx = toImpl(relatedContext);
+            Global::platform()->didLoadModule(ctx, toImpl(referrer), mp->m_loadedScript);
+            mp->m_loadedScript->moduleData()->m_didCallLoadedCallback = true;
+        }
+    }
+
+    if (result.error) {
+        mp->m_value = toImpl(result.error.value());
+        Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* {
+            promise->reject(state, promise);
+            return ValueRef::createUndefined();
+        },
+                           result.error.value(), promise);
+    } else {
+        Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* {
+            promise->fulfill(state, promise);
+            return ValueRef::createUndefined();
+        },
+                           result.error.value(), promise);
+    }
+}
+
+void* PlatformRef::threadLocalCustomData()
+{
+    return ThreadLocal::customData();
+}
+
 bool thread_local Globals::g_globalsInited = false;
-void Globals::initialize()
+void Globals::initialize(PlatformRef* platform)
 {
-    // initialize global value or context
+    // initialize global value or context including thread-local variables
     // this function should be invoked once at the start of the program
+    // argument `platform` will be deleted automatically when Globals::finalize called
     RELEASE_ASSERT(!g_globalsInited);
-    Heap::initialize();
-    VMInstance::initialize();
+    Global::initialize(new PlatformBridge(platform));
+    ThreadLocal::initialize();
     g_globalsInited = true;
 }
 
 void Globals::finalize()
 {
-    // finalize global value or context
+    // finalize global value or context including thread-local variables
     // this function should be invoked once at the end of the program
     RELEASE_ASSERT(!!g_globalsInited);
-    Heap::finalize();
-    VMInstance::finalize();
+    ThreadLocal::finalize();
+
+    // Global::finalize should be called at the end of program
+    // because it holds Platform which could be used in other Object's finalizer
+    Global::finalize();
     g_globalsInited = false;
 }
 
+void Globals::initializeThread()
+{
+    // initialize thread-local variables
+    // this function should be invoked at the start of sub-thread
+    RELEASE_ASSERT(!g_globalsInited);
+    ThreadLocal::initialize();
+    g_globalsInited = true;
+}
+
+void Globals::finalizeThread()
+{
+    // finalize thread-local variables
+    // this function should be invoked once at the end of sub-thread
+    RELEASE_ASSERT(!!g_globalsInited);
+    ThreadLocal::finalize();
+    g_globalsInited = false;
+}
+
+bool Globals::supportsThreading()
+{
+#if defined(ENABLE_THREADING)
+    return true;
+#else
+    return false;
+#endif
+}
+
+const char* Globals::version()
+{
+    return ESCARGOT_VERSION;
+}
+
+const char* Globals::buildDate()
+{
+    return ESCARGOT_BUILD_DATE;
+}
+
 void* Memory::gcMalloc(size_t siz)
 {
     return GC_MALLOC(siz);
@@ -517,9 +686,13 @@ OptionalRef<StringRef> RopeStringRef::right()
     }
 }
 
-SymbolRef* SymbolRef::create(StringRef* desc)
+SymbolRef* SymbolRef::create(OptionalRef<StringRef> desc)
 {
-    return toRef(new Symbol(toImpl(desc)));
+    if (desc) {
+        return toRef(new Symbol(toImpl(desc.value())));
+    } else {
+        return toRef(new Symbol());
+    }
 }
 
 SymbolRef* SymbolRef::fromGlobalSymbolRegistry(VMInstanceRef* vm, StringRef* desc)
@@ -527,12 +700,12 @@ SymbolRef* SymbolRef::fromGlobalSymbolRegistry(VMInstanceRef* vm, StringRef* des
     return toRef(Symbol::fromGlobalSymbolRegistry(toImpl(vm), toImpl(desc)));
 }
 
-StringRef* SymbolRef::description()
+OptionalRef<StringRef> SymbolRef::description()
 {
     if (toImpl(this)->description().hasValue()) {
         return toRef(toImpl(this)->description().value());
     }
-    return toRef(String::emptyString);
+    return nullptr;
 }
 
 StringRef* SymbolRef::symbolDescriptiveString()
@@ -705,105 +878,6 @@ bool BigIntRef::isNegative()
     return toImpl(this)->isNegative();
 }
 
-class PlatformBridge : public Platform {
-public:
-    PlatformBridge(PlatformRef* p)
-        : m_platform(p)
-    {
-    }
-
-    virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte) override
-    {
-        return m_platform->onMallocArrayBufferObjectDataBuffer(sizeInByte);
-    }
-
-    virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) override
-    {
-        m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte);
-    }
-
-    virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) override
-    {
-        return m_platform->onReallocArrayBufferObjectDataBuffer(oldBuffer, oldSizeInByte, newSizeInByte);
-    }
-
-    virtual void markJSJobEnqueued(Context* relatedContext) override
-    {
-        m_platform->markJSJobEnqueued(toRef(relatedContext));
-    }
-
-    virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) override
-    {
-        LoadModuleResult result;
-        auto refResult = m_platform->onLoadModule(toRef(relatedContext), toRef(whereRequestFrom), toRef(moduleSrc));
-
-        result.script = toImpl(refResult.script.get());
-        result.errorMessage = toImpl(refResult.errorMessage);
-        result.errorCode = refResult.errorCode;
-
-        return result;
-    }
-
-    virtual void didLoadModule(Context* relatedContext, Optional<Script*> whereRequestFrom, Script* loadedModule) override
-    {
-        if (whereRequestFrom) {
-            m_platform->didLoadModule(toRef(relatedContext), toRef(whereRequestFrom.value()), toRef(loadedModule));
-        } else {
-            m_platform->didLoadModule(toRef(relatedContext), nullptr, toRef(loadedModule));
-        }
-    }
-
-    virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) override
-    {
-        m_platform->hostImportModuleDynamically(toRef(relatedContext), toRef(referrer), toRef(src), toRef(promise));
-    }
-
-    PlatformRef* m_platform;
-};
-
-void PlatformRef::notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult)
-{
-    auto result = Evaluator::execute(relatedContext, [](ExecutionStateRef* state, LoadModuleResult loadModuleResult, Script::ModuleData::ModulePromiseObject* promise) -> ValueRef* {
-        if (loadModuleResult.script) {
-            if (loadModuleResult.script.value()->isExecuted()) {
-                if (loadModuleResult.script.value()->wasThereErrorOnModuleEvaluation()) {
-                    state->throwException(loadModuleResult.script.value()->moduleEvaluationError());
-                }
-            }
-        } else {
-            state->throwException(ErrorObjectRef::create(state, loadModuleResult.errorCode, loadModuleResult.errorMessage));
-        }
-        return ValueRef::createUndefined();
-    },
-                                     loadModuleResult, (Script::ModuleData::ModulePromiseObject*)promise);
-
-    Script::ModuleData::ModulePromiseObject* mp = (Script::ModuleData::ModulePromiseObject*)promise;
-    mp->m_referrer = toImpl(referrer);
-    if (loadModuleResult.script.hasValue()) {
-        mp->m_loadedScript = toImpl(loadModuleResult.script.value());
-        if (!mp->m_loadedScript->moduleData()->m_didCallLoadedCallback) {
-            Context* ctx = toImpl(relatedContext);
-            ctx->vmInstance()->platform()->didLoadModule(ctx, toImpl(referrer), mp->m_loadedScript);
-            mp->m_loadedScript->moduleData()->m_didCallLoadedCallback = true;
-        }
-    }
-
-    if (result.error) {
-        mp->m_value = toImpl(result.error.value());
-        Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* {
-            promise->reject(state, promise);
-            return ValueRef::createUndefined();
-        },
-                           result.error.value(), promise);
-    } else {
-        Evaluator::execute(relatedContext, [](ExecutionStateRef* state, ValueRef* error, PromiseObjectRef* promise) -> ValueRef* {
-            promise->fulfill(state, promise);
-            return ValueRef::createUndefined();
-        },
-                           result.error.value(), promise);
-    }
-}
-
 Evaluator::StackTraceData::StackTraceData()
     : src(toRef(String::emptyString))
     , sourceCode(toRef(String::emptyString))
@@ -931,14 +1005,9 @@ COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Resolve == (int)VMInstance::
 COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::Before == (int)VMInstance::PromiseHookType::Before, "");
 COMPILE_ASSERT((int)VMInstanceRef::PromiseHookType::After == (int)VMInstance::PromiseHookType::After, "");
 
-PersistentRefHolder<VMInstanceRef> VMInstanceRef::create(PlatformRef* platform, const char* locale, const char* timezone, const char* baseCacheDir)
+PersistentRefHolder<VMInstanceRef> VMInstanceRef::create(const char* locale, const char* timezone, const char* baseCacheDir)
 {
-    return PersistentRefHolder<VMInstanceRef>(toRef(new VMInstance(new PlatformBridge(platform), locale, timezone, baseCacheDir)));
-}
-
-PlatformRef* VMInstanceRef::platform()
-{
-    return ((PlatformBridge*)toImpl(this)->platform())->m_platform;
+    return PersistentRefHolder<VMInstanceRef>(toRef(new VMInstance(locale, timezone, baseCacheDir)));
 }
 
 void VMInstanceRef::setOnVMInstanceDelete(OnVMInstanceDelete cb)
@@ -2053,6 +2122,15 @@ bool ContextRef::initDebugger(const char* options)
 #endif /* ESCARGOT_DEBUGGER */
 }
 
+bool ContextRef::isDebuggerRunning()
+{
+#ifdef ESCARGOT_DEBUGGER
+    return !!toImpl(this)->debugger() && toImpl(this)->debugger()->enabled();
+#else /* !ESCARGOT_DEBUGGER */
+    return false;
+#endif /* ESCARGOT_DEBUGGER */
+}
+
 void ContextRef::printDebugger(StringRef* output)
 {
 #ifdef ESCARGOT_DEBUGGER
@@ -2767,9 +2845,9 @@ RegExpObjectRef::RegExpObjectOption RegExpObjectRef::option()
     return (RegExpObjectRef::RegExpObjectOption)toImpl(this)->option();
 }
 
-BackingStoreRef* BackingStoreRef::create(VMInstanceRef* instance, size_t byteLength)
+BackingStoreRef* BackingStoreRef::create(size_t byteLength)
 {
-    return toRef(new BackingStore(toImpl(instance), byteLength));
+    return toRef(new BackingStore(byteLength));
 }
 
 BackingStoreRef* BackingStoreRef::create(void* data, size_t byteLength, BackingStoreRef::BackingStoreRefDeleterCallback callback, void* callbackData)
@@ -2792,9 +2870,28 @@ bool BackingStoreRef::isShared()
     return toImpl(this)->isShared();
 }
 
-void BackingStoreRef::reallocate(VMInstanceRef* instance, size_t newByteLength)
+void BackingStoreRef::reallocate(size_t newByteLength)
+{
+    toImpl(this)->reallocate(newByteLength);
+}
+
+OptionalRef<BackingStoreRef> ArrayBufferRef::backingStore()
 {
-    toImpl(this)->reallocate(toImpl(instance), newByteLength);
+    if (toImpl(this)->backingStore()) {
+        return toRef(toImpl(this)->backingStore().value());
+    } else {
+        return nullptr;
+    }
+}
+
+uint8_t* ArrayBufferRef::rawBuffer()
+{
+    return (uint8_t*)toImpl(this)->data();
+}
+
+size_t ArrayBufferRef::byteLength()
+{
+    return toImpl(this)->byteLength();
 }
 
 ArrayBufferObjectRef* ArrayBufferObjectRef::create(ExecutionStateRef* state)
@@ -2817,41 +2914,33 @@ void ArrayBufferObjectRef::detachArrayBuffer()
     toImpl(this)->detachArrayBuffer();
 }
 
-OptionalRef<BackingStoreRef> ArrayBufferObjectRef::backingStore()
-{
-    if (toImpl(this)->backingStore()) {
-        return toRef(toImpl(this)->backingStore().value());
-    } else {
-        return nullptr;
-    }
-}
-
-uint8_t* ArrayBufferObjectRef::rawBuffer()
+bool ArrayBufferObjectRef::isDetachedBuffer()
 {
-    return (uint8_t*)toImpl(this)->data();
+    return toImpl(this)->isDetachedBuffer();
 }
-
-size_t ArrayBufferObjectRef::byteLength()
+#if defined(ENABLE_THREADING)
+SharedArrayBufferObjectRef* SharedArrayBufferObjectRef::create(ExecutionStateRef* state, size_t byteLength)
 {
-    return toImpl(this)->byteLength();
+    return toRef(new SharedArrayBufferObject(*toImpl(state), toImpl(state)->context()->globalObject()->sharedArrayBufferPrototype(), byteLength));
 }
-
-bool ArrayBufferObjectRef::isDetachedBuffer()
+#else
+SharedArrayBufferObjectRef* SharedArrayBufferObjectRef::create(ExecutionStateRef* state, size_t byteLength)
 {
-    return toImpl(this)->isDetachedBuffer();
+    RELEASE_ASSERT_NOT_REACHED();
 }
+#endif
 
-ArrayBufferObjectRef* ArrayBufferViewRef::buffer()
+ArrayBufferRef* ArrayBufferViewRef::buffer()
 {
     return toRef(toImpl(this)->buffer());
 }
 
-void ArrayBufferViewRef::setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength)
+void ArrayBufferViewRef::setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength)
 {
     toImpl(this)->setBuffer(toImpl(bo), byteOffset, byteLength, arrayLength);
 }
 
-void ArrayBufferViewRef::setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength)
+void ArrayBufferViewRef::setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength)
 {
     toImpl(this)->setBuffer(toImpl(bo), byteOffset, byteLength);
 }
@@ -3340,6 +3429,11 @@ void FunctionTemplateRef::setName(AtomicStringRef* name)
     toImpl(this)->setName(toImpl(name));
 }
 
+void FunctionTemplateRef::setLength(size_t length)
+{
+    toImpl(this)->setLength(length);
+}
+
 void FunctionTemplateRef::updateCallbackFunction(FunctionTemplateRef::NativeFunctionPointer fn)
 {
     toImpl(this)->updateCallbackFunction(fn);
@@ -3468,6 +3562,26 @@ PlatformRef::LoadModuleResult::LoadModuleResult(ErrorObjectRef::Code errorCode,
 {
 }
 
+bool SerializerRef::serializeInto(ValueRef* value, std::ostringstream& output)
+{
+    return Serializer::serializeInto(toImpl(value), output);
+}
+
+ValueRef* SerializerRef::deserializeFrom(ContextRef* context, std::istringstream& input)
+{
+    std::unique_ptr<SerializedValue> value = Serializer::deserializeFrom(input);
+
+    SandBox sb(toImpl(context));
+    auto result = sb.run([](ExecutionState& state, void* data) -> Value {
+        std::unique_ptr<SerializedValue>* value = (std::unique_ptr<SerializedValue>*)data;
+        return value->get()->toValue(state);
+    },
+                         &value);
+
+    ASSERT(result.error.isEmpty());
+    return toRef(result.result);
+}
+
 #if defined(ENABLE_WASM)
 ValueRef* WASMOperationsRef::copyStableBufferBytes(ExecutionStateRef* state, ValueRef* source)
 {
index b0f3c2be70dc3eb3db2d64691c03c1a9ae3ea007..216bbb1a729a4b9d053d97cf0bc65a437d173c78 100644 (file)
 #include <tuple>
 #include <type_traits>
 #include <utility>
+#include <sstream>
 
 #if !defined(NDEBUG) && defined(__GLIBCXX__) && !defined(_GLIBCXX_DEBUG)
 #pragma message("You should define `_GLIBCXX_DEBUG` in {debug mode + libstdc++} because Escargot uses it")
 #endif
 
 #define ESCARGOT_POINTERVALUE_CHILD_REF_LIST(F) \
+    F(ArrayBuffer)                              \
     F(ArrayBufferObject)                        \
     F(ArrayBufferView)                          \
     F(ArrayObject)                              \
@@ -65,6 +67,7 @@
     F(ProxyObject)                              \
     F(RegExpObject)                             \
     F(SetObject)                                \
+    F(SharedArrayBufferObject)                  \
     F(String)                                   \
     F(StringObject)                             \
     F(Symbol)                                   \
@@ -124,10 +127,20 @@ class ESCARGOT_EXPORT Globals {
     static thread_local bool g_globalsInited;
 
 public:
-    // Escargot has thread-isoloate Globals.
-    // Users need to call initialize, finalize function for each thread
-    static void initialize();
+    // Escargot has thread-independent Globals.
+    // Users should call initialize, finalize once in the main program
+    static void initialize(PlatformRef* platform);
     static void finalize();
+
+    // Globals also used for thread initialization
+    // Users need to call initializeThread, finalizeThread function for each thread
+    static void initializeThread();
+    static void finalizeThread();
+
+    static bool supportsThreading();
+
+    static const char* version();
+    static const char* buildDate();
 };
 
 class ESCARGOT_EXPORT Memory {
@@ -603,7 +616,7 @@ class ESCARGOT_EXPORT VMInstanceRef {
 public:
     // you can to provide timezone as TZ database name like "US/Pacific".
     // if you don't provide, we try to detect system timezone.
-    static PersistentRefHolder<VMInstanceRef> create(PlatformRef* platform, const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr);
+    static PersistentRefHolder<VMInstanceRef> create(const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr);
 
     typedef void (*OnVMInstanceDelete)(VMInstanceRef* instance);
     void setOnVMInstanceDelete(OnVMInstanceDelete cb);
@@ -630,8 +643,6 @@ public:
     // you can call this function if you don't want to use every alive contexts
     void clearCachesRelatedWithContext();
 
-    PlatformRef* platform();
-
     SymbolRef* toStringTagSymbol();
     SymbolRef* iteratorSymbol();
     SymbolRef* unscopablesSymbol();
@@ -667,6 +678,7 @@ public:
     void throwException(ValueRef* exceptionValue); // if you use this function without Evaluator, your program will crash :(
 
     bool initDebugger(const char* options);
+    bool isDebuggerRunning();
     void printDebugger(StringRef* output);
     StringRef* getClientSource(StringRef** sourceName);
 
@@ -922,9 +934,9 @@ public:
 
 class ESCARGOT_EXPORT SymbolRef : public PointerValueRef {
 public:
-    static SymbolRef* create(StringRef* desc);
+    static SymbolRef* create(OptionalRef<StringRef> desc);
     static SymbolRef* fromGlobalSymbolRegistry(VMInstanceRef* context, StringRef* desc); // this is same with Symbol.for
-    StringRef* description();
+    OptionalRef<StringRef> description();
     StringRef* symbolDescriptiveString();
 };
 
@@ -1462,7 +1474,7 @@ class ESCARGOT_EXPORT BackingStoreRef {
     friend class ArrayBufferObject;
 
 public:
-    static BackingStoreRef* create(VMInstanceRef* instance, size_t byteLength);
+    static BackingStoreRef* create(size_t byteLength);
     typedef void (*BackingStoreRefDeleterCallback)(void* data, size_t length,
                                                    void* deleterData);
     static BackingStoreRef* create(void* data, size_t byteLength, BackingStoreRefDeleterCallback callback, void* callbackData);
@@ -1471,27 +1483,35 @@ public:
     size_t byteLength();
     // Indicates whether the backing store is Shared Data Block (for SharedArrayBuffer)
     bool isShared();
-    void reallocate(VMInstanceRef* instance, size_t newByteLength);
+    void reallocate(size_t newByteLength);
 };
 
-class ESCARGOT_EXPORT ArrayBufferObjectRef : public ObjectRef {
+class ESCARGOT_EXPORT ArrayBufferRef : public ObjectRef {
+public:
+    OptionalRef<BackingStoreRef> backingStore();
+    uint8_t* rawBuffer();
+    size_t byteLength();
+};
+
+class ESCARGOT_EXPORT ArrayBufferObjectRef : public ArrayBufferRef {
 public:
     static ArrayBufferObjectRef* create(ExecutionStateRef* state);
     void allocateBuffer(ExecutionStateRef* state, size_t bytelength);
     void attachBuffer(BackingStoreRef* backingStore);
     void detachArrayBuffer();
-
-    OptionalRef<BackingStoreRef> backingStore();
-    uint8_t* rawBuffer();
-    size_t byteLength();
     bool isDetachedBuffer();
 };
 
+class ESCARGOT_EXPORT SharedArrayBufferObjectRef : public ArrayBufferRef {
+public:
+    static SharedArrayBufferObjectRef* create(ExecutionStateRef* state, size_t bytelength);
+};
+
 class ESCARGOT_EXPORT ArrayBufferViewRef : public ObjectRef {
 public:
-    ArrayBufferObjectRef* buffer();
-    void setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength);
-    void setBuffer(ArrayBufferObjectRef* bo, size_t byteOffset, size_t byteLength);
+    ArrayBufferRef* buffer();
+    void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength, size_t arrayLength);
+    void setBuffer(ArrayBufferRef* bo, size_t byteOffset, size_t byteLength);
     uint8_t* rawBuffer();
     size_t byteLength();
     size_t byteOffset();
@@ -1741,6 +1761,13 @@ struct ESCARGOT_EXPORT ObjectTemplateNamedPropertyHandlerData {
     }
 };
 
+class ESCARGOT_EXPORT SerializerRef {
+public:
+    // returns the serialization was successful
+    static bool serializeInto(ValueRef* value, std::ostringstream& output);
+    static ValueRef* deserializeFrom(ContextRef* context, std::istringstream& input);
+};
+
 class ESCARGOT_EXPORT ObjectTemplateRef : public TemplateRef {
 public:
     static ObjectTemplateRef* create();
@@ -1763,7 +1790,10 @@ public:
     static FunctionTemplateRef* create(AtomicStringRef* name, size_t argumentCount, bool isStrict, bool isConstructor,
                                        FunctionTemplateRef::NativeFunctionPointer fn);
 
+    // setName and setLength should be called before instantiate
     void setName(AtomicStringRef* name);
+    void setLength(size_t length);
+
     void updateCallbackFunction(FunctionTemplateRef::NativeFunctionPointer fn);
 
     ObjectTemplateRef* prototypeTemplate();
@@ -1857,6 +1887,22 @@ public:
         notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, onLoadModule(relatedContext, referrer, src));
     }
     void notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult);
+
+    // ThreadLocal custom data
+    // PlatformRef should not have any member variables
+    // Instead, user could allocate thread-local values through following methods
+    virtual void* allocateThreadLocalCustomData()
+    {
+        // do nothing
+        return nullptr;
+    }
+
+    virtual void deallocateThreadLocalCustomData()
+    {
+        // do nothing
+    }
+
+    void* threadLocalCustomData();
 };
 
 #if defined(ENABLE_WASM)
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArray.cpp
new file mode 100644 (file)
index 0000000..83aec02
--- /dev/null
@@ -0,0 +1,1996 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+#include "runtime/ErrorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "interpreter/ByteCodeInterpreter.h"
+
+namespace Escargot {
+
+Value builtinArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    bool interpretArgumentsAsElements = false;
+    uint64_t size = 0;
+    if (argc > 1) {
+        size = argc;
+        interpretArgumentsAsElements = true;
+    } else if (argc == 1) {
+        Value& val = argv[0];
+        if (val.isNumber()) {
+            if (val.equalsTo(state, Value(val.toUint32(state)))) {
+                size = val.toNumber(state);
+            } else {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::GlobalObject_InvalidArrayLength);
+            }
+        } else {
+            size = 1;
+            interpretArgumentsAsElements = true;
+        }
+    }
+
+    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+
+    // Let proto be ? GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%").
+    // Let array be ! ArrayCreate(0, proto).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->arrayPrototype();
+    });
+    ArrayObject* array = new ArrayObject(state, proto, size);
+
+    if (interpretArgumentsAsElements) {
+        Value val = argv[0];
+        if (argc > 1 || !val.isInt32()) {
+            if (array->isFastModeArray()) {
+                for (size_t idx = 0; idx < argc; idx++) {
+                    array->m_fastModeData[idx] = argv[idx];
+                }
+            } else {
+                for (size_t idx = 0; idx < argc; idx++) {
+                    array->ArrayObject::defineOwnProperty(state, ObjectPropertyName(state, idx), ObjectPropertyDescriptor(val, ObjectPropertyDescriptor::AllPresent));
+                    val = argv[idx + 1];
+                }
+            }
+        }
+    }
+    return array;
+}
+
+#define CHECK_ARRAY_LENGTH(COND)                                                                                               \
+    if (COND) {                                                                                                                \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_InvalidArrayLength); \
+    }
+
+static Object* arraySpeciesCreate(ExecutionState& state, Object* originalArray, const int64_t length)
+{
+    ASSERT(originalArray != nullptr);
+    // Assert: length is an integer Number >= 0.
+    ASSERT(length >= 0);
+
+    // Let C be undefined.
+    Value C;
+    // Let isArray be IsArray(originalArray).
+    // If isArray is true, then
+    if (originalArray->isArray(state)) {
+        // Let C be Get(originalArray, "constructor").
+        C = originalArray->get(state, ObjectPropertyName(state.context()->staticStrings().constructor)).value(state, originalArray);
+
+        // If IsConstructor(C) is true, then
+        if (C.isConstructor()) {
+            // Let thisRealm be the running execution context’s Realm.
+            Context* thisRealm = state.context();
+            // Let realmC be GetFunctionRealm(C).
+            Context* realmC = C.asObject()->getFunctionRealm(state);
+
+            // ReturnIfAbrupt(realmC).
+            // If thisRealm and realmC are not the same Realm Record, then
+            // If SameValue(C, realmC.[[intrinsics]].[[%Array%]]) is true, let C be undefined.
+            if (thisRealm != realmC) {
+                if (C.asPointerValue() == realmC->globalObject()->array()) {
+                    C = Value();
+                }
+            }
+        }
+        // If Type(C) is Object, then
+        if (C.isObject()) {
+            // a. Set C be Get(C, @@species).
+            C = C.asObject()->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species)).value(state, C);
+            if (C.isNull()) { // b. If C is null, set C to undefined.
+                C = Value();
+            }
+        }
+    }
+
+    // If C is undefined, return ArrayCreate(length).
+    if (C.isUndefined()) {
+        return new ArrayObject(state, static_cast<uint64_t>(length));
+    }
+    // If IsConstructor(C) is false, throw a TypeError exception.
+    if (!C.isConstructor()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
+    }
+    // Return Construct(C, <<length>>).
+    Value argv[1] = { Value(length) };
+    return Object::construct(state, C, 1, argv).toObject(state);
+}
+
+// http://ecma-international.org/ecma-262/10.0/#sec-flattenintoarray
+// FlattenIntoArray(target, source, sourceLen, start, depth [ , mapperFunction, thisArg ])
+static int64_t flattenIntoArray(ExecutionState& state, Value target, Value source, int64_t sourceLen, int64_t start, double depth, Value mappedValue = Value(Value::EmptyValue), Value thisArg = Value(Value::EmptyValue))
+{
+    ASSERT(target.isObject());
+    ASSERT(source.isObject());
+    ASSERT(sourceLen >= 0);
+
+    int64_t targetIndex = start;
+    int64_t sourceIndex = 0;
+
+    while (sourceIndex < sourceLen) {
+        String* p = Value(sourceIndex).toString(state);
+        ObjectHasPropertyResult exists = source.asObject()->hasIndexedProperty(state, p);
+        if (exists) {
+            Value element = exists.value(state, ObjectPropertyName(state, p), source);
+            if (!mappedValue.isEmpty()) {
+                Value args[] = { element, Value(sourceIndex), source };
+                ASSERT(!thisArg.isEmpty() && depth == 1);
+                element = Object::call(state, mappedValue, thisArg, 3, args);
+            }
+            if (depth > 0 && element.isObject() && element.asObject()->isArray(state)) {
+                int64_t elementLen = element.asObject()->length(state);
+                targetIndex = flattenIntoArray(state, target, element, elementLen, targetIndex, depth - 1);
+
+            } else {
+                if (targetIndex >= std::numeric_limits<int64_t>::max()) {
+                    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "invalid index");
+                }
+                target.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, targetIndex),
+                                                                    ObjectPropertyDescriptor(element, ObjectPropertyDescriptor::AllPresent));
+                targetIndex++;
+            }
+        }
+        sourceIndex++;
+    }
+    return targetIndex;
+}
+
+static Value builtinArrayIsArray(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ASSERT(argv != nullptr);
+
+    return Value(argv[0].isObject() && argv[0].asObject()->isArray(state));
+}
+
+// Array.from ( items [ , mapfn [ , thisArg ] ] )#
+static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value items = argv[0];
+    Value mapfn;
+    if (argc > 1) {
+        mapfn = argv[1];
+    }
+    Value thisArg;
+    if (argc > 2) {
+        thisArg = argv[2];
+    }
+    // Let C be the this value.
+    Value C = thisValue;
+    Value T;
+    // If mapfn is undefined, let mapping be false.
+    bool mapping = false;
+    if (!mapfn.isUndefined()) {
+        // If IsCallable(mapfn) is false, throw a TypeError exception.
+        if (!mapfn.isCallable()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "argument map function should be undefined or function");
+        }
+        // If thisArg was supplied, let T be thisArg; else let T be undefined.
+        T = thisArg;
+        // Let mapping be true.
+        mapping = true;
+    }
+
+    // Let usingIterator be ? GetMethod(items, @@iterator).
+    Value usingIterator = Object::getMethod(state, items, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
+    // If usingIterator is not undefined, then
+    if (!usingIterator.isUndefined()) {
+        Object* A;
+        // If IsConstructor(C) is true, then
+        if (C.isConstructor()) {
+            // Let A be ? Construct(C).
+            A = Object::construct(state, C, 0, nullptr).toObject(state);
+        } else {
+            // Let A be ArrayCreate(0).
+            A = new ArrayObject(state);
+        }
+        // Let iteratorRecord be ? GetIterator(items, sync, usingIterator).
+        IteratorRecord* iteratorRecord = IteratorObject::getIterator(state, items, true, usingIterator);
+
+        // Let k be 0.
+        int64_t k = 0;
+        // Repeat
+        while (true) {
+            // If k ≥ 2^53-1, then
+            if (k >= ((1LL << 53LL) - 1LL)) {
+                // Let error be ThrowCompletion(a newly created TypeError object).
+                // Return ? IteratorClose(iteratorRecord, error).
+                Value throwCompletion = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("Got invalid index"));
+                return IteratorObject::iteratorClose(state, iteratorRecord, throwCompletion, true);
+            }
+            // Let Pk be ! ToString(k).
+            ObjectPropertyName pk(state, k);
+            // Let next be ? IteratorStep(iteratorRecord).
+            Optional<Object*> next = IteratorObject::iteratorStep(state, iteratorRecord);
+            // If next is false, then
+            if (!next.hasValue()) {
+                // Perform ? Set(A, "length", k, true).
+                A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(k), A);
+                // Return A.
+                return A;
+            }
+            // Let nextValue be ? IteratorValue(next).
+            Value nextValue = IteratorObject::iteratorValue(state, next.value());
+            Value mappedValue;
+            // If mapping is true, then
+            if (mapping) {
+                // Let mappedValue be Call(mapfn, T, « nextValue, k »).
+                // If mappedValue is an abrupt completion, return ? IteratorClose(iteratorRecord, mappedValue).
+                // Set mappedValue to mappedValue.[[Value]].
+                Value argv[] = { nextValue, Value(k) };
+                try {
+                    mappedValue = Object::call(state, mapfn, T, 2, argv);
+                } catch (const Value& v) {
+                    Value exceptionValue = v;
+                    return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+                }
+            } else {
+                mappedValue = nextValue;
+            }
+
+            try {
+                // Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
+                A->defineOwnPropertyThrowsException(state, pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
+            } catch (const Value& v) {
+                // If defineStatus is an abrupt completion, return ? IteratorClose(iteratorRecord, defineStatus).
+                Value exceptionValue = v;
+                return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+            }
+            // Increase k by 1.
+            k++;
+        }
+    }
+    // NOTE: items is not an Iterable so assume it is an array-like object.
+    // Let arrayLike be ! ToObject(items).
+    Object* arrayLike = items.toObject(state);
+    // Let len be ? ToLength(? Get(arrayLike, "length")).
+    uint64_t len = arrayLike->length(state);
+    // If IsConstructor(C) is true, then
+    Object* A;
+    if (C.isConstructor()) {
+        // Let A be ? Construct(C, « len »).
+        Value vlen(len);
+        A = Object::construct(state, C, 1, &vlen).toObject(state);
+    } else {
+        // Else,
+        // Let A be ? ArrayCreate(len).
+        A = new ArrayObject(state, len);
+    }
+
+    // Let k be 0.
+    uint64_t k = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ! ToString(k).
+        ObjectPropertyName Pk(state, k);
+        // Let kValue be ? Get(arrayLike, Pk).
+        Value kValue = arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike);
+        // If mapping is true, then
+        Value mappedValue;
+        if (mapping) {
+            // Let mappedValue be ? Call(mapfn, T, « kValue, k »).
+            Value argv[] = { kValue, Value(k) };
+            mappedValue = Object::call(state, mapfn, T, 2, argv);
+        } else {
+            // Else, let mappedValue be kValue.
+            mappedValue = kValue;
+        }
+        // Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
+        A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
+        // Increase k by 1.
+        k++;
+    }
+    // Perform ? Set(A, "length", len, true).
+    A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(len), A);
+    // Return A.
+    return A;
+}
+
+// Array.of ( ...items )
+static Value builtinArrayOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    size_t len = argc;
+    Value C = thisValue;
+
+    Object* A;
+    if (C.isConstructor()) {
+        Value arg[1] = { Value(len) };
+        A = Object::construct(state, C, 1, arg).toObject(state);
+    } else {
+        A = new ArrayObject(state, static_cast<uint64_t>(len));
+    }
+
+    size_t k = 0;
+    while (k < len) {
+        Value kValue = argv[k];
+        ObjectPropertyName Pk(state, k);
+        A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(kValue, ObjectPropertyDescriptor::AllPresent));
+        k++;
+    }
+    A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(len), A);
+
+    return A;
+}
+
+static Value builtinArrayJoin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisBinded, Array, join);
+    int64_t len = thisBinded->length(state);
+    Value separator = argv[0];
+    String* sep;
+
+    if (separator.isUndefined()) {
+        sep = state.context()->staticStrings().asciiTable[(size_t)','].string();
+    } else {
+        sep = separator.toString(state);
+    }
+
+    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(thisBinded)) {
+        return String::emptyString;
+    }
+    ToStringRecursionPreventerItemAutoHolder holder(state, thisBinded);
+
+    StringBuilder builder;
+    int64_t prevIndex = 0;
+    int64_t curIndex = 0;
+    while (curIndex < len) {
+        if (curIndex != 0 && sep->length() > 0) {
+            if (static_cast<double>(builder.contentLength()) > static_cast<double>(STRING_MAXIMUM_LENGTH - (curIndex - prevIndex - 1) * (int64_t)sep->length())) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
+            }
+            while (curIndex - prevIndex > 1) {
+                builder.appendString(sep);
+                prevIndex++;
+            }
+            builder.appendString(sep);
+        }
+        Value elem = thisBinded->getIndexedProperty(state, Value(curIndex)).value(state, thisBinded);
+
+        if (!elem.isUndefinedOrNull()) {
+            builder.appendString(elem.toString(state));
+        }
+        prevIndex = curIndex;
+        if (elem.isUndefined()) {
+            struct Data {
+                bool exists;
+                int64_t cur;
+                int64_t ret;
+            } data;
+            data.exists = false;
+            data.cur = curIndex;
+            data.ret = len;
+
+            Value ptr = thisBinded;
+            while (ptr.isObject()) {
+                if (!ptr.asObject()->isOrdinary()) {
+                    curIndex++;
+                    break;
+                }
+                ptr.asObject()->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& name, const ObjectStructurePropertyDescriptor& desc, void* data) {
+                    int64_t index;
+                    Data* e = (Data*)data;
+                    int64_t* ret = &e->ret;
+                    Value key = name.toPlainValue(state);
+                    index = key.toNumber(state);
+                    if ((uint64_t)index != Value::InvalidIndexValue) {
+                        if (self->get(state, name).value(state, self).isUndefined()) {
+                            return true;
+                        }
+                        if (index > e->cur && e->ret > index) {
+                            e->ret = std::min(index, e->ret);
+                        }
+                    }
+                    return true;
+                },
+                                            &data);
+                ptr = ptr.asObject()->getPrototype(state);
+            }
+            curIndex = data.ret;
+        } else {
+            curIndex++;
+        }
+    }
+    if (sep->length() > 0) {
+        if (static_cast<double>(builder.contentLength()) > static_cast<double>(STRING_MAXIMUM_LENGTH - (curIndex - prevIndex - 1) * (int64_t)sep->length())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
+        }
+        while (curIndex - prevIndex > 1) {
+            builder.appendString(sep);
+            prevIndex++;
+        }
+    }
+    return builder.finalize(&state);
+}
+
+static Value builtinArrayReverse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reverse);
+    int64_t len = O->length(state);
+    int64_t middle = std::floor(len / 2);
+    int64_t lower = 0;
+    while (middle > lower) {
+        int64_t upper = len - lower - 1;
+        ObjectPropertyName upperP = ObjectPropertyName(state, upper);
+        ObjectPropertyName lowerP = ObjectPropertyName(state, lower);
+
+        auto lowerExists = O->hasIndexedProperty(state, Value(lower));
+        Value lowerValue;
+        if (lowerExists) {
+            lowerValue = lowerExists.value(state, lowerP, O);
+        }
+        auto upperExists = O->hasIndexedProperty(state, Value(upper));
+        Value upperValue;
+        if (upperExists) {
+            upperValue = upperExists.value(state, upperP, O);
+        }
+        if (lowerExists && upperExists) {
+            O->setThrowsException(state, lowerP, upperValue, O);
+            O->setThrowsException(state, upperP, lowerValue, O);
+        } else if (!lowerExists && upperExists) {
+            O->setThrowsException(state, lowerP, upperValue, O);
+            O->deleteOwnPropertyThrowsException(state, upperP);
+        } else if (lowerExists && !upperExists) {
+            O->deleteOwnPropertyThrowsException(state, lowerP);
+            O->setThrowsException(state, upperP, lowerValue, O);
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, lower, middle, result);
+            int64_t nextLower = result;
+            Object::nextIndexBackward(state, O, upper, middle, result);
+            int64_t nextUpper = result;
+            int64_t x = middle - nextLower;
+            int64_t y = nextUpper - middle;
+            int64_t lowerCandidate;
+            if (x > y) {
+                lowerCandidate = nextLower;
+            } else {
+                lowerCandidate = len - nextUpper - 1;
+            }
+            if (lower == lowerCandidate)
+                break;
+            lower = lowerCandidate;
+            continue;
+        }
+        lower++;
+    }
+
+    return O;
+}
+
+static Value builtinArraySort(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, sort);
+    Value cmpfn = argv[0];
+    if (!cmpfn.isUndefined() && !cmpfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
+    }
+    bool defaultSort = (argc == 0) || cmpfn.isUndefined();
+
+    int64_t len = thisObject->length(state);
+
+    thisObject->sort(state, len, [defaultSort, &cmpfn, &state](const Value& a, const Value& b) -> bool {
+        if (a.isEmpty() && b.isUndefined())
+            return false;
+        if (a.isUndefined() && b.isEmpty())
+            return true;
+        if (a.isEmpty() || a.isUndefined())
+            return false;
+        if (b.isEmpty() || b.isUndefined())
+            return true;
+        Value arg[2] = { a, b };
+        if (defaultSort) {
+            String* vala = a.toString(state);
+            String* valb = b.toString(state);
+            return *vala < *valb;
+        } else {
+            Value ret = Object::call(state, cmpfn, Value(), 2, arg);
+            return (ret.toNumber(state) < 0);
+        } });
+    return thisObject;
+}
+
+static Value builtinArraySplice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // TODO(ES6): the number of actual arguments is used.
+    // e.g. var arr = [1, 2, 3, 4, 5];
+    //      Different: arr.splice(2) vs. arr.splice(2, undefined)
+
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, splice);
+
+    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // Let relativeStart be ToInteger(start).
+    double relativeStart = argv[0].toInteger(state);
+
+    // If relativeStart is negative, let actualStart be max((len + relativeStart),0); else let actualStart be min(relativeStart, len).
+    int64_t actualStart = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
+
+    int64_t insertCount;
+    int64_t actualDeleteCount;
+
+    // If the number of actual arguments is 0, then
+    if (argc == 0) {
+        // Let insertCount be 0.
+        insertCount = 0;
+        // Let actualDeleteCount be 0.
+        actualDeleteCount = 0;
+    } else if (argc == 1) {
+        // Else if the number of actual arguments is 1, then
+        // Let insertCount be 0.
+        insertCount = 0;
+        // Let actualDeleteCount be len – actualStart.
+        actualDeleteCount = len - actualStart;
+    } else {
+        // Else,
+        // Let insertCount be the number of actual arguments minus 2.
+        insertCount = argc - 2;
+        // Let dc be ToInteger(deleteCount).
+        double dc = argv[1].toInteger(state);
+        // Let actualDeleteCount be min(max(dc,0), len – actualStart).
+        actualDeleteCount = std::min(std::max(dc, 0.0), (double)(len - actualStart));
+    }
+    // If len+insertCount−actualDeleteCount > 2^53-1, throw a TypeError exception.
+    CHECK_ARRAY_LENGTH(len + insertCount - actualDeleteCount > Value::maximumLength());
+    // Let A be ArraySpeciesCreate(O, actualDeleteCount).
+    Object* A = arraySpeciesCreate(state, O, actualDeleteCount);
+
+    // Let k be 0.
+    int64_t k = 0;
+
+    // Repeat, while k < actualDeleteCount
+    while (k < actualDeleteCount) {
+        // Let from be ToString(actualStart+k).
+        // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
+        // If fromPresent is true, then
+        // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
+        ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(actualStart + k));
+        if (fromValue) {
+            // Call the [[DefineOwnProperty]] internal method of A with arguments ToString(k), Property Descriptor {[[Value]]: fromValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+            ObjectPropertyName from(state, Value(actualStart + k));
+            A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, k),
+                                                ObjectPropertyDescriptor(fromValue.value(state, from, O), ObjectPropertyDescriptor::AllPresent));
+        }
+        // Increment k by 1.
+        k++;
+    }
+    // Let setStatus be Set(A, "length", actualDeleteCount, true).
+    A->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(actualDeleteCount), A);
+
+    // Let items be an internal List whose elements are, in left to right order, the portion of the actual argument list starting with item1. The list will be empty if no such items are present.
+    Value* items = nullptr;
+    int64_t itemCount = 0;
+
+    if (argc > 2) {
+        items = argv + 2;
+        itemCount = argc - 2;
+    }
+
+    // If itemCount < actualDeleteCount, then
+    if (itemCount < actualDeleteCount) {
+        // Let k be actualStart.
+        k = actualStart;
+        // move [actualStart + deleteCnt, len) to [actualStart + insertCnt, len - deleteCnt + insertCnt)
+        while (k < len - actualDeleteCount) {
+            // Let from be ToString(k+actualDeleteCount).
+            int64_t from = k + actualDeleteCount;
+            // Let to be ToString(k+itemCount).
+            int64_t to = k + itemCount;
+            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
+            ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(from));
+            // If fromPresent is true, then
+            if (fromValue) {
+                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
+                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
+                O->setIndexedPropertyThrowsException(state, Value(to), fromValue.value(state, ObjectPropertyName(state, from), O));
+            } else {
+                // Else, fromPresent is false
+
+                // Call the [[Delete]] internal method of O with arguments to and true.
+                O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(to)));
+            }
+            k++;
+        }
+        // delete [len - deleteCnt + itemCount, len)
+        // Let k be len.
+        k = len;
+        // Repeat, while k > (len – actualDeleteCount + itemCount)
+        while (k > len - actualDeleteCount + itemCount) {
+            // Call the [[Delete]] internal method of O with arguments ToString(k–1) and true.
+            O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(k - 1)));
+            // Decrease k by 1.
+            k--;
+        }
+    } else if (itemCount > actualDeleteCount) {
+        // Else if itemCount > actualDeleteCount, then
+
+        // Let k be (len – actualDeleteCount).
+        k = len - actualDeleteCount;
+
+        // Repeat, while k > actualStart
+        while (k > actualStart) {
+            // Let from be ToString(k + actualDeleteCount – 1).
+            // Let to be ToString(k + itemCount – 1)
+
+            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
+            ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(k + actualDeleteCount - 1));
+            // If fromPresent is true, then
+            if (fromValue) {
+                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
+                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
+                ObjectPropertyName from(state, k + actualDeleteCount - 1);
+                O->setIndexedPropertyThrowsException(state, Value(k + itemCount - 1), fromValue.value(state, from, O));
+            } else {
+                // Else, fromPresent is false
+                // Call the [[Delete]] internal method of O with argument to and true.
+                ObjectPropertyName to(state, k + itemCount - 1);
+                O->deleteOwnPropertyThrowsException(state, to);
+            }
+            // Decrease k by 1.
+            k--;
+        }
+    }
+
+    // Let k be actualStart.
+    k = actualStart;
+
+    // while items is not empty
+    int64_t itemsIndex = 0;
+    while (itemsIndex < itemCount) {
+        // Remove the first element from items and let E be the value of that element.
+        Value E = items[itemsIndex++];
+        // Call the [[Put]] internal method of O with arguments ToString(k), E, and true.
+        O->setIndexedPropertyThrowsException(state, Value(k), E);
+        // Increase k by 1.
+        k++;
+    }
+
+    O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - actualDeleteCount + itemCount), O);
+    return A;
+}
+
+
+static Value builtinArrayToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, toString);
+    Value toString = thisObject->get(state, state.context()->staticStrings().join).value(state, thisObject);
+    if (!toString.isCallable()) {
+        toString = state.context()->globalObject()->objectPrototypeToString();
+    }
+    return Object::call(state, toString, thisObject, 0, nullptr);
+}
+
+static Value builtinArrayConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, concat);
+    Object* obj = arraySpeciesCreate(state, thisObject, 0);
+    int64_t n = 0;
+    for (size_t i = 0; i < argc + 1; i++) {
+        Value argi = (i == 0) ? thisObject : argv[i - 1];
+        if (argi.isObject()) {
+            Object* arr = argi.asObject();
+
+            // Let spreadable be IsConcatSpreadable(E).
+            bool spreadable = arr->isConcatSpreadable(state);
+
+            if (spreadable) {
+                // Let k be 0.
+                int64_t k = 0;
+                // Let len be the result of calling the [[Get]] internal method of E with argument "length".
+                int64_t len = arr->length(state);
+
+                // If n + len > 2^53 - 1, throw a TypeError exception.
+                CHECK_ARRAY_LENGTH(n + len > Value::maximumLength());
+
+                // Repeat, while k < len
+                while (k < len) {
+                    // Let exists be the result of calling the [[HasProperty]] internal method of E with P.
+                    ObjectHasPropertyResult exists = arr->hasIndexedProperty(state, Value(k));
+                    if (exists) {
+                        obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n + k)), ObjectPropertyDescriptor(exists.value(state, ObjectPropertyName(state, k), arr), ObjectPropertyDescriptor::AllPresent));
+                        k++;
+                    } else {
+                        int64_t result;
+                        Object::nextIndexForward(state, arr, k, len, result);
+                        k = result;
+                    }
+                }
+
+                n += len;
+                obj->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(n), obj);
+            } else {
+                // If n >= 2^53 - 1, throw a TypeError exception.
+                CHECK_ARRAY_LENGTH(n >= Value::maximumLength());
+
+                obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n)), ObjectPropertyDescriptor(arr, ObjectPropertyDescriptor::AllPresent));
+                n++;
+            }
+        } else {
+            obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n++)), ObjectPropertyDescriptor(argi, ObjectPropertyDescriptor::AllPresent));
+        }
+    }
+
+    return obj;
+}
+
+static Value builtinArraySlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, slice);
+    int64_t len = thisObject->length(state);
+    double relativeStart = argv[0].toInteger(state);
+    int64_t k = (relativeStart < 0) ? std::max((double)len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
+    int64_t kStart = k;
+    double relativeEnd = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
+    int64_t finalEnd = (relativeEnd < 0) ? std::max((double)len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
+
+    int64_t n = 0;
+    // Let count be max(final - k, 0).
+    // Let A be ArraySpeciesCreate(O, count).
+    Object* ArrayObject = arraySpeciesCreate(state, thisObject, std::max(((int64_t)finalEnd - (int64_t)k), (int64_t)0));
+    while (k < finalEnd) {
+        ObjectHasPropertyResult exists = thisObject->hasIndexedProperty(state, Value(k));
+        if (exists) {
+            ArrayObject->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n)),
+                                                          ObjectPropertyDescriptor(exists.value(state, ObjectPropertyName(state, k), thisObject), ObjectPropertyDescriptor::AllPresent));
+            k++;
+            n++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, thisObject, k, len, result);
+            n += result - k;
+            k = result;
+        }
+    }
+    if (finalEnd - kStart > 0) {
+        ArrayObject->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(finalEnd - kStart), Value(ArrayObject));
+    } else {
+        ArrayObject->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), Value(ArrayObject));
+    }
+    return ArrayObject;
+}
+
+static Value builtinArrayForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, forEach);
+    int64_t len = thisObject->length(state);
+
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1)
+        T = argv[1];
+
+    int64_t k = 0;
+    while (k < len) {
+        Value Pk = Value(k);
+        auto res = thisObject->hasProperty(state, ObjectPropertyName(state, Pk));
+        if (res) {
+            Value kValue = res.value(state, ObjectPropertyName(state, k), thisObject);
+            Value args[3] = { kValue, Pk, thisObject };
+            Object::call(state, callbackfn, T, 3, args);
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, thisObject, k, len, result);
+            k = result;
+            continue;
+        }
+    }
+    return Value();
+}
+
+static Value builtinArrayIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, indexOf);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If len is 0, return -1.
+    if (len == 0) {
+        return Value(-1);
+    }
+
+    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
+    double n = 0;
+    if (argc > 1) {
+        n = argv[1].toInteger(state);
+    }
+
+    // If n ≥ len, return -1.
+    if (n >= len) {
+        return Value(-1);
+    }
+
+    double doubleK;
+    // If n ≥ 0, then
+    if (n >= 0) {
+        // Let k be n.
+        doubleK = (n == -0) ? 0 : n;
+    } else {
+        // Else, n<0
+        // Let k be len - abs(n).
+        doubleK = len - std::abs(n);
+
+        // If k is less than 0, then let k be 0.
+        if (doubleK < 0) {
+            doubleK = 0;
+        }
+    }
+
+    ASSERT(doubleK >= 0);
+    int64_t k = doubleK;
+
+    // Repeat, while k<len
+    while (k < len) {
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
+        auto kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
+            Value elementK = kPresent.value(state, ObjectPropertyName(state, k), O);
+
+            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
+            if (elementK.equalsTo(state, argv[0])) {
+                // If same is true, return k.
+                return Value(k);
+            }
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+            continue;
+        }
+        // Increase k by 1.
+        k++;
+    }
+
+    // Return -1.
+    return Value(-1);
+}
+
+static Value builtinArrayLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, lastIndexOf);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If len is 0, return -1.
+    if (len == 0) {
+        return Value(-1);
+    }
+
+    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
+    double n;
+    if (argc > 1) {
+        n = argv[1].toInteger(state);
+    } else {
+        n = len - 1;
+    }
+
+    // If n ≥ 0, then let k be min(n, len – 1).
+    int64_t k;
+    if (n >= 0) {
+        k = (n == -0) ? 0 : std::min(n, len - 1.0);
+    } else {
+        // Else, n < 0
+        // Let k be len - abs(n).
+        k = len - std::abs(n);
+    }
+
+    // Repeat, while k≥ 0
+    while (k >= 0) {
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
+        auto kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
+            Value elementK = kPresent.value(state, ObjectPropertyName(state, k), O);
+
+            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
+            if (elementK.equalsTo(state, argv[0])) {
+                // If same is true, return k.
+                return Value(k);
+            }
+        } else {
+            int64_t result;
+            Object::nextIndexBackward(state, O, k, -1, result);
+            k = result;
+            continue;
+        }
+        // Decrease k by 1.
+        k--;
+    }
+
+    // Return -1.
+    return Value(-1);
+}
+
+static Value builtinArrayEvery(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, every);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1)
+        T = argv[1];
+
+    // Let k be 0.
+    int64_t k = 0;
+
+    while (k < len) {
+        // Let Pk be ToString(k).
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        auto kPresent = O->hasIndexedProperty(state, Value(k));
+
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
+            // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+            Value args[] = { kValue, Value(k), O };
+            Value testResult = Object::call(state, callbackfn, T, 3, args);
+
+            if (!testResult.toBoolean(state)) {
+                return Value(false);
+            }
+
+            // Increae k by 1.
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+        }
+    }
+    return Value(true);
+}
+
+static Value builtinArrayFill(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, fill);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // Let relativeStart be ToInteger(start).
+    double relativeStart = 0;
+    if (argc > 1) {
+        relativeStart = argv[1].toInteger(state);
+    }
+
+    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
+    int64_t k = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
+
+    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
+    double relativeEnd = len;
+    if (argc > 2 && !argv[2].isUndefined()) {
+        relativeEnd = argv[2].toInteger(state);
+    }
+
+    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
+    int64_t fin = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
+
+    Value value = argv[0];
+    while (k < fin) {
+        O->setIndexedPropertyThrowsException(state, Value(k), value);
+        k++;
+    }
+    // return O.
+    return O;
+}
+
+static Value builtinArrayFilter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, filter);
+
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1)
+        T = argv[1];
+
+    // Let A be ArraySpeciesCreate(O, 0).
+    Object* A = arraySpeciesCreate(state, O, 0);
+
+    // Let k be 0.
+    int64_t k = 0;
+    // Let to be 0.
+    int64_t to = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ToString(k).
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
+
+            // Let selected be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+            Value v[] = { kValue, Value(k), O };
+            Value selected = Object::call(state, callbackfn, T, 3, v);
+
+            // If ToBoolean(selected) is true, then
+            if (selected.toBoolean(state)) {
+                // Let status be CreateDataPropertyOrThrow (A, ToString(to), kValue).
+                ASSERT(A != nullptr);
+                A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(to)), ObjectPropertyDescriptor(kValue, ObjectPropertyDescriptor::AllPresent));
+                // Increase to by 1
+                to++;
+            }
+
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+        }
+        // Increase k by 1.
+    }
+
+    // Return A.
+    return A;
+}
+
+static Value builtinArrayMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, map);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1)
+        T = argv[1];
+
+    // Let A be ArraySpeciesCreate(O, len).
+    Object* A = arraySpeciesCreate(state, O, len);
+
+    // Let k be 0.
+    int64_t k = 0;
+
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ToString(k).
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        auto kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            auto Pk = ObjectPropertyName(state, k);
+            Value kValue = kPresent.value(state, Pk, O);
+            // Let mappedValue be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+            Value v[] = { kValue, Value(k), O };
+            Value mappedValue = Object::call(state, callbackfn, T, 3, v);
+            // Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue).
+            A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+        }
+        // Increase k by 1.
+    }
+
+    return A;
+}
+
+static Value builtinArraySome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, some);
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().some.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    Value T;
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let k be 0.
+    int64_t k = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ToString(k).
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            ObjectPropertyName Pk(state, k);
+            Value kValue = kPresent.value(state, Pk, O);
+            // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+            Value argv[] = { kValue, Value(k), O };
+            Value testResult = Object::call(state, callbackfn, T, 3, argv);
+            // If ToBoolean(testResult) is true, return true.
+            if (testResult.toBoolean(state)) {
+                return Value(true);
+            }
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+            continue;
+        }
+        // Increase k by 1.
+        k++;
+    }
+    // Return false.
+    return Value(false);
+}
+
+// Array.prototype.includes ( searchElement [ , fromIndex ] )
+static Value builtinArrayIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, includes);
+    // Let len be ? ToLength(? Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If len is 0, return false.
+    if (len == 0) {
+        return Value(false);
+    }
+
+    Value searchElement = argv[0];
+    // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
+    double n = argc >= 2 ? argv[1].toInteger(state) : 0;
+    double doubleK;
+    // If n ≥ 0, then
+    if (n >= 0) {
+        // Let k be n.
+        doubleK = n;
+    } else {
+        // Else n < 0,
+        // Let k be len + n.
+        doubleK = len + n;
+    }
+
+    // If k < 0, let k be 0.
+    if (doubleK < 0) {
+        doubleK = 0;
+    }
+
+    ASSERT(doubleK >= 0);
+
+    // Repeat, while k < len
+    while (doubleK < len) {
+        // Let elementK be the result of ? Get(O, ! ToString(k)).
+        Value elementK = O->get(state, ObjectPropertyName(state, Value(doubleK))).value(state, O);
+        // If SameValueZero(searchElement, elementK) is true, return true.
+        if (elementK.equalsToByTheSameValueZeroAlgorithm(state, searchElement)) {
+            return Value(true);
+        }
+        // Increase k by 1.
+        doubleK++;
+    }
+
+    // Return false.
+    return Value(false);
+}
+
+static Value builtinArrayToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sup-array.prototype.tolocalestring
+    // Let array be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(array, Array, toLocaleString);
+
+    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(array)) {
+        return String::emptyString;
+    }
+    ToStringRecursionPreventerItemAutoHolder holder(state, array);
+
+    // Let len be ? ToLength(? Get(array, "length")).
+    uint64_t len = array->length(state);
+
+    // Let separator be the String value for the list-separator String appropriate for the host environment’s current locale (this is derived in an implementation-defined way).
+    String* separator = state.context()->staticStrings().asciiTable[(size_t)','].string();
+
+    // Let R be the empty String.
+    String* R = String::emptyString;
+
+    // Let k be 0.
+    uint64_t k = 0;
+
+    // Repeat, while k < len
+    while (k < len) {
+        // If k > 0, then
+        if (k > 0) {
+            // Set R to the string-concatenation of R and separator.
+            StringBuilder builder;
+            builder.appendString(R);
+            builder.appendString(separator);
+            R = builder.finalize(&state);
+        }
+        // Let nextElement be ? Get(array, ! ToString(k)).
+        Value nextElement = array->getIndexedProperty(state, Value(k)).value(state, array);
+        // If nextElement is not undefined or null, then
+        if (!nextElement.isUndefinedOrNull()) {
+            // Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)).
+            Value func = nextElement.toObject(state)->get(state, state.context()->staticStrings().toLocaleString).value(state, nextElement);
+            String* S = Object::call(state, func, nextElement, argc, argv).toString(state);
+            // Set R to the string-concatenation of R and S.
+            StringBuilder builder;
+            builder.appendString(R);
+            builder.appendString(S);
+            R = builder.finalize(&state);
+        }
+        // Increase k by 1.
+        k++;
+    }
+
+    // Return R.
+    return R;
+}
+
+static Value builtinArrayReduce(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reduce);
+    int64_t len = O->length(state); // 2-3
+    Value callbackfn = argv[0];
+    Value initialValue = Value(Value::EmptyValue);
+    if (argc > 1) {
+        initialValue = argv[1];
+    }
+
+    if (!callbackfn.isCallable()) // 4
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+
+    if (len == 0 && (initialValue.isUndefined() || initialValue.isEmpty())) // 5
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+
+    int64_t k = 0; // 6
+    Value accumulator;
+    if (!initialValue.isEmpty()) { // 7
+        accumulator = initialValue;
+    } else { // 8
+        ObjectHasPropertyResult kPresent; // 8.a
+        while (!kPresent && k < len) { // 8.b
+            kPresent = O->hasIndexedProperty(state, Value(k)); // 8.b.ii
+            if (kPresent) {
+                accumulator = kPresent.value(state, ObjectPropertyName(state, k), O);
+            }
+            k++; // 8.b.iv
+        }
+        if (!kPresent)
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+    }
+    while (k < len) { // 9
+        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k)); // 9.b
+        if (kPresent) { // 9.c
+            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O); // 9.c.i
+            const int fnargc = 4;
+            Value fnargs[] = { accumulator, kValue, Value(k), O };
+            accumulator = Object::call(state, callbackfn, Value(), fnargc, fnargs);
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            k = result;
+        }
+    }
+    return accumulator;
+}
+
+static Value builtinArrayReduceRight(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reduceRight);
+
+    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
+                                       state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If len is 0 and initialValue is not present, throw a TypeError exception.
+    if (len == 0 && argc < 2) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+    }
+
+    // Let k be len-1.
+    int64_t k = len - 1;
+
+    Value accumulator;
+    // If initialValue is present, then
+    if (argc > 1) {
+        // Set accumulator to initialValue.
+        accumulator = argv[1];
+    } else {
+        // Else, initialValue is not present
+        // Let kPresent be false.
+        ObjectHasPropertyResult kPresent;
+
+        // Repeat, while kPresent is false and k ≥ 0
+        while (!kPresent && k >= 0) {
+            // Let Pk be ToString(k).
+            // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+            kPresent = O->hasIndexedProperty(state, Value(k));
+
+            // If kPresent is true, then
+            if (kPresent) {
+                // Let accumulator be the result of calling the [[Get]] internal method of O with argument Pk.
+                accumulator = kPresent.value(state, ObjectPropertyName(state, k), O);
+            }
+
+            // Decrease k by 1.
+            int64_t result;
+            Object::nextIndexBackward(state, O, k, -1, result);
+            k = result;
+        }
+        // If kPresent is false, throw a TypeError exception.
+        if (!kPresent) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+        }
+    }
+
+    // Repeat, while k ≥ 0
+    while (k >= 0) {
+        // Let Pk be ToString(k).
+        ObjectPropertyName Pk(state, k);
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
+
+            // Let accumulator be the result of calling the [[Call]] internal method of callbackfn with undefined as the this value and argument list containing accumulator, kValue, k, and O.
+            Value v[] = { accumulator, kValue, Value(k), O };
+            accumulator = Object::call(state, callbackfn, Value(), 4, v);
+        }
+
+        // Decrease k by 1.
+        int64_t result;
+        Object::nextIndexBackward(state, O, k, -1, result);
+        k = result;
+    }
+
+    // Return accumulator.
+    return accumulator;
+}
+
+static Value builtinArrayPop(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, pop);
+
+    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
+    // Let len be ToUint32(lenVal).
+    int64_t len = O->length(state);
+
+    // If len is zero,
+    if (len == 0) {
+        // Call the [[Put]] internal method of O with arguments "length", 0, and true.
+        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), O);
+        // Return undefined.
+        return Value();
+    } else {
+        // Else, len > 0
+        // Let indx be ToString(len–1).
+        ObjectPropertyName indx(state, len - 1);
+        // Let element be the result of calling the [[Get]] internal method of O with argument indx.
+        Value element = O->get(state, indx).value(state, O);
+        // Call the [[Delete]] internal method of O with arguments indx and true.
+        O->deleteOwnPropertyThrowsException(state, indx);
+        // Call the [[Put]] internal method of O with arguments "length", indx, and true.
+        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - 1), O);
+        // Return element.
+        return element;
+    }
+}
+
+static Value builtinArrayPush(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, push);
+
+    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t n = O->length(state);
+
+    // If len + argCount > 2^53 - 1, throw a TypeError exception.
+    CHECK_ARRAY_LENGTH((uint64_t)n + argc > Value::maximumLength());
+
+    // Let items be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.
+    // Repeat, while items is not empty
+    // Remove the first element from items and let E be the value of the element.
+    for (size_t i = 0; i < argc; i++) {
+        // Call the [[Put]] internal method of O with arguments ToString(n), E, and true.
+        O->setIndexedPropertyThrowsException(state, Value(n), argv[i]);
+        // Increase n by 1.
+        n++;
+    }
+
+    // Call the [[Put]] internal method of O with arguments "length", n, and true.
+    O->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(n), O);
+
+    // Return n.
+    return Value(n);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-array.prototype.flat
+// Array.prototype.flat( [ depth ] )
+static Value builtinArrayFlat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, flat);
+    int64_t sourceLen = O->length(state);
+    double depthNum = 1;
+    if (argc > 0 && !argv[0].isUndefined()) {
+        depthNum = argv[0].toInteger(state);
+    }
+    Object* A = arraySpeciesCreate(state, O, 0);
+    flattenIntoArray(state, A, O, sourceLen, 0, depthNum);
+
+    return A;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-array.prototype.flatmap
+// Array.prototype.flatMap ( mapperFunction [ , thisArg ] )
+static Value builtinArrayFlatMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, flatMap);
+    int64_t sourceLen = O->length(state);
+    if (!argv[0].isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().flatMap.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
+    }
+    Value t;
+    if (argc > 1) {
+        t = argv[1];
+    }
+    Object* A = arraySpeciesCreate(state, O, 0);
+    flattenIntoArray(state, A, O, sourceLen, 0, 1, argv[0], t);
+    return A;
+}
+
+static Value builtinArrayShift(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, shift);
+    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+    // If len is zero, then
+    if (len == 0) {
+        // Call the [[Put]] internal method of O with arguments "length", 0, and true.
+        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), O);
+        // Return undefined.
+        return Value();
+    }
+    // Let first be the result of calling the [[Get]] internal method of O with argument "0".
+    Value first = O->get(state, ObjectPropertyName(state, Value(0))).value(state, O);
+    // Let k be 1.
+    int64_t k = 1;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let from be ToString(k).
+        ObjectPropertyName from(state, k);
+        // Let to be ToString(k–1).
+        ObjectPropertyName to(state, k - 1);
+        // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
+        auto fromPresent = O->hasIndexedProperty(state, Value(k));
+
+        // If fromPresent is true, then
+        if (fromPresent) {
+            // Let fromVal be the result of calling the [[Get]] internal method of O with argument from.
+            Value fromVal = fromPresent.value(state, from, O);
+            // Call the [[Put]] internal method of O with arguments to, fromVal, and true.
+            O->setThrowsException(state, to, fromVal, O);
+        } else {
+            // Else, fromPresent is false
+            // Call the [[Delete]] internal method of O with arguments to and true.
+            O->deleteOwnPropertyThrowsException(state, to);
+        }
+
+        // Increase k by 1.
+        if (fromPresent) {
+            k++;
+        } else {
+            int64_t result;
+            Object::nextIndexForward(state, O, k, len, result);
+            int64_t r = result;
+            if (r > k) {
+                k = r;
+            } else {
+                k--;
+            }
+        }
+    }
+    // Call the [[Delete]] internal method of O with arguments ToString(len–1) and true.
+    O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(len - 1)));
+    // Call the [[Put]] internal method of O with arguments "length", (len–1) , and true.
+    O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - 1), O);
+    // Return first.
+    return first;
+}
+
+static Value builtinArrayUnshift(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, unshift);
+    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
+    // Let len be ToLength(Get(O, "length")).
+    int64_t len = O->length(state);
+
+    // Let argCount be the number of actual arguments.
+    int64_t argCount = argc;
+    // Let k be len.
+    int64_t k = len;
+
+    // If argCount > 0, then
+    // this line add in newer version ECMAScript than ECMAScript 5.1
+    // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.unshift
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.13
+    if (argCount) {
+        // If len + argCount > 2^53 - 1, throw a TypeError exception.
+        CHECK_ARRAY_LENGTH(len + argCount > Value::maximumLength());
+
+        // Repeat, while k > 0,
+        while (k > 0) {
+            // Let from be ToString(k–1).
+            // Let to be ToString(k+argCount –1).
+            ObjectPropertyName to(state, k + argCount - 1);
+
+            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
+            ObjectHasPropertyResult fromPresent = O->hasIndexedProperty(state, Value(k - 1));
+            // If fromPresent is true, then
+            if (fromPresent) {
+                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
+                ObjectPropertyName from(state, k - 1);
+                Value fromValue = fromPresent.value(state, from, O);
+                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
+                O->setThrowsException(state, to, fromValue, O);
+            } else {
+                // Else, fromPresent is false
+                // Call the [[Delete]] internal method of O with arguments to, and true.
+                O->deleteOwnPropertyThrowsException(state, to);
+            }
+
+            if (fromPresent) {
+                // Decrease k by 1.
+                k--;
+            } else {
+                int64_t result;
+                Object::nextIndexBackward(state, O, k, -1, result);
+                int64_t r = std::max(result + 1, result - argCount + 1);
+                if (r < k && std::abs(r - k) > argCount) {
+                    k = r;
+                } else {
+                    k--;
+                }
+            }
+        }
+
+        // Let j be 0.
+        int64_t j = 0;
+        // Let items be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.
+        Value* items = argv;
+
+        // Repeat, while items is not empty
+        while (j < argCount) {
+            // Remove the first element from items and let E be the value of that element.
+            Value E = items[j];
+            // Call the [[Put]] internal method of O with arguments ToString(j), E, and true.
+            O->setThrowsException(state, ObjectPropertyName(state, Value(j)), E, O);
+            // Increase j by 1.
+            j++;
+        }
+    }
+
+    // Call the [[Put]] internal method of O with arguments "length", len+argCount, and true.
+    O->setThrowsException(state, state.context()->staticStrings().length, Value(len + argCount), O);
+
+    // Return len+argCount.
+    return Value(len + argCount);
+}
+
+// Array.prototype.find ( predicate [ , thisArg ] )#
+static Value builtinArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, find);
+    // Let len be ? ToLength(? Get(O, "length")).
+    double len = O->length(state);
+    // If IsCallable(predicate) is false, throw a TypeError exception.
+    if (!argv[0].isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    Value T;
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    if (argc >= 2) {
+        T = argv[1];
+    }
+    // Let k be 0.
+    double k = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ! ToString(k).
+        // Let kValue be ? Get(O, Pk).
+        Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
+        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+        Value v[] = { kValue, Value(k), O };
+        bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
+        // If testResult is true, return kValue.
+        if (testResult) {
+            return kValue;
+        }
+        // Increase k by 1.
+        k++;
+    }
+    // Return undefined.
+    return Value();
+}
+
+// Array.prototype.findIndex ( predicate [ , thisArg ] )#
+static Value builtinArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, findIndex);
+    // Let len be ? ToLength(? Get(O, "length")).
+    double len = O->length(state);
+    // If IsCallable(predicate) is false, throw a TypeError exception.
+    if (!argv[0].isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    Value T;
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    if (argc >= 2) {
+        T = argv[1];
+    }
+    // Let k be 0.
+    double k = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let Pk be ! ToString(k).
+        // Let kValue be ? Get(O, Pk).
+        Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
+        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+        Value v[] = { kValue, Value(k), O };
+        bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
+        // If testResult is true, return k.
+        if (testResult) {
+            return Value(k);
+        }
+        // Increase k by 1.
+        k++;
+    }
+    // Return -1
+    return Value(-1);
+}
+
+// Array.prototype.copyWithin (target, start [ , end ] )
+static Value builtinArrayCopyWithin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, copyWithin);
+    // Let len be ToLength(Get(O, "length")).
+    double len = O->length(state);
+    // Let relativeTarget be ToInteger(target).
+    double relativeTarget = argv[0].toInteger(state);
+    // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len).
+    double to = (relativeTarget < 0.0) ? std::max((len + relativeTarget), 0.0) : std::min(relativeTarget, len);
+    // Let relativeStart be ToInteger(start).
+    double relativeStart = argv[1].toInteger(state);
+    // If relativeStart < 0, let from be max((len + relativeStart),0); else let from be min(relativeStart, len).
+    double from = (relativeStart < 0.0) ? std::max((len + relativeStart), 0.0) : std::min(relativeStart, len);
+    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
+    double relativeEnd = (argc < 3 || argv[2].isUndefined()) ? len : argv[2].toInteger(state);
+    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
+    double finalEnd = (relativeEnd < 0.0) ? std::max((len + relativeEnd), 0.0) : std::min(relativeEnd, len);
+    // Let count be min(final-from, len-to).
+    double count = std::min(finalEnd - from, len - to);
+    int8_t direction;
+    // If from<to and to<from+count
+    if (from < to && to < from + count) {
+        // Let direction be -1.
+        direction = -1;
+        // Let from be from + count -1.
+        from = from + count - 1;
+        // Let to be to + count -1.
+        to = to + count - 1;
+    } else {
+        // Let direction = 1.
+        direction = 1;
+    }
+
+    int64_t intCount = count;
+    int64_t intFrom = from;
+    int64_t intTo = to;
+
+    // Repeat, while count > 0
+    while (intCount > 0) {
+        // Let fromPresent be HasProperty(O, fromKey).
+        ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(intFrom));
+        // If fromPresent is true, then
+        if (fromValue) {
+            // Let setStatus be Set(O, toKey, fromVal, true).
+            O->setIndexedPropertyThrowsException(state, Value(intTo), fromValue.value(state, ObjectPropertyName(state, intFrom), O));
+        } else {
+            // Let deleteStatus be DeletePropertyOrThrow(O, toKey).
+            O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(intTo)));
+        }
+        // Let from be from + direction.
+        intFrom += direction;
+        // Let to be to + direction.
+        intTo += direction;
+        // Let count be count − 1.
+        intCount--;
+    }
+    // Return O.
+    return O;
+}
+
+static Value builtinArrayKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, keys);
+    return M->keys(state);
+}
+
+static Value builtinArrayValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, values);
+    return M->values(state);
+}
+
+static Value builtinArrayEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, entries);
+    return M->entries(state);
+}
+
+static Value builtinArrayIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isArrayIteratorObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+
+    ArrayIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asArrayIteratorObject();
+    return iter->next(state);
+}
+
+static Value builtinArrayAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(obj, Array, entries);
+    size_t len = obj->length(state);
+    double relativeStart = argv[0].toInteger(state);
+    if (relativeStart < 0) {
+        relativeStart = len + relativeStart;
+    }
+    if (relativeStart < 0 || relativeStart >= len) {
+        return Value();
+    }
+    return obj->getIndexedProperty(state, Value(relativeStart)).value(state, thisValue);
+}
+
+void GlobalObject::installArray(ExecutionState& state)
+{
+    m_array = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Array, builtinArrayConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_array->setGlobalIntrinsicObject(state);
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_array->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    m_arrayPrototype = new ArrayPrototypeObject(state);
+    m_arrayPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_arrayPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().isArray),
+                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().isArray, builtinArrayIsArray, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().from),
+                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().from, builtinArrayFrom, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().of),
+                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().of, builtinArrayOf, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().concat),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().concat, builtinArrayConcat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinArrayForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().indexOf),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().indexOf, builtinArrayIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndexOf),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().lastIndexOf, builtinArrayLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().join),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().join, builtinArrayJoin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sort),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sort, builtinArraySort, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().splice),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().splice, builtinArraySplice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().slice),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().slice, builtinArraySlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().every),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().every, builtinArrayEvery, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().fill),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().fill, builtinArrayFill, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().includes),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().includes, builtinArrayIncludes, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().filter),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().filter, builtinArrayFilter, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reduce),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reduce, builtinArrayReduce, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reduceRight),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reduceRight, builtinArrayReduceRight, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().pop),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().pop, builtinArrayPop, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().push),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().push, builtinArrayPush, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().shift),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().shift, builtinArrayShift, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reverse),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reverse, builtinArrayReverse, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toString),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinArrayToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().map),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().map, builtinArrayMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().some),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().some, builtinArraySome, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinArrayToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().unshift),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().unshift, builtinArrayUnshift, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keys, builtinArrayKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().find),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().find, builtinArrayFind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().findIndex),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().findIndex, builtinArrayFindIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().copyWithin),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().copyWithin, builtinArrayCopyWithin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().flat),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().flat, builtinArrayFlat, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().flatMap),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().flatMap, builtinArrayFlatMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().at),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().at, builtinArrayAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    Object* blackList = new Object(state);
+    blackList->markThisObjectDontNeedStructureTransitionTable();
+    blackList->setPrototype(state, Value(Value::Null));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().at), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().copyWithin), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().entries), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().fill), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().find), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().findIndex), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keys), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().values), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().includes), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().flat), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().flatMap), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+
+    FunctionObject* values = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinArrayValues, 0, NativeFunctionInfo::Strict));
+    // Well-Known Intrinsic Objects : %ArrayProto_values%
+    // The initial value of the values data property of %ArrayPrototype%
+    m_arrayPrototypeValues = values;
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values),
+                                                       ObjectPropertyDescriptor(values, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                       ObjectPropertyDescriptor(values,
+                                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
+                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinArrayEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().unscopables),
+                                                       ObjectPropertyDescriptor(blackList, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_array->setFunctionPrototype(state, m_arrayPrototype);
+
+    m_arrayIteratorPrototype = new Object(state, m_iteratorPrototype);
+    m_arrayIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_arrayIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinArrayIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                               ObjectPropertyDescriptor(Value(String::fromASCII("Array Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Array),
+                      ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinArrayBuffer.cpp
new file mode 100644 (file)
index 0000000..8216f25
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ArrayBufferObject.h"
+
+namespace Escargot {
+
+// https://262.ecma-international.org/#sec-arraybuffer-constructor
+static Value builtinArrayBufferConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    uint64_t byteLength = argv[0].toIndex(state);
+    if (byteLength == Value::InvalidIndexValue) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
+    }
+
+    return ArrayBufferObject::allocateArrayBuffer(state, newTarget.value(), byteLength);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-arraybuffer.isview
+static Value builtinArrayBufferIsView(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+
+    Object* obj = argv[0].asObject();
+    if (obj->isTypedArrayObject() || obj->isDataViewObject()) {
+        return Value(true);
+    }
+
+    return Value(false);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-arraybuffer.prototype.bytelength
+static Value builtinArrayBufferByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+
+    ArrayBufferObject* obj = thisValue.asObject()->asArrayBufferObject();
+#if defined(ENABLE_THREADING)
+    if (obj->isSharedArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+#endif
+
+    if (obj->isDetachedBuffer()) {
+        return Value(0);
+    }
+
+    return Value(obj->byteLength());
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-arraybuffer.prototype.slice
+static Value builtinArrayBufferSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+
+    ArrayBufferObject* obj = thisValue.asObject()->asArrayBufferObject();
+#if defined(ENABLE_THREADING)
+    if (obj->isSharedArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+#endif
+    obj->throwTypeErrorIfDetached(state);
+
+    double len = obj->byteLength();
+    double relativeStart = argv[0].toInteger(state);
+    size_t first = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, len);
+    double relativeEnd = argv[1].isUndefined() ? len : argv[1].toInteger(state);
+    double final_ = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, len);
+    size_t newLen = std::max((int)final_ - (int)first, 0);
+
+    Value constructor = obj->speciesConstructor(state, state.context()->globalObject()->arrayBuffer());
+    Value arguments[] = { Value(newLen) };
+    Object* newValue = Object::construct(state, constructor, 1, arguments).toObject(state);
+    if (!newValue->isArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
+    }
+
+    ArrayBufferObject* newObject = newValue->asArrayBufferObject();
+    newObject->throwTypeErrorIfDetached(state);
+
+    if (newObject == obj) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
+    }
+
+    if (newObject->byteLength() < newLen) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
+    }
+    obj->throwTypeErrorIfDetached(state);
+
+    newObject->fillData(obj->data() + first, newLen);
+    return newObject;
+}
+
+void GlobalObject::installArrayBuffer(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    m_arrayBuffer = new NativeFunctionObject(state, NativeFunctionInfo(strings->ArrayBuffer, builtinArrayBufferConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_arrayBuffer->setGlobalIntrinsicObject(state);
+
+    m_arrayBuffer->defineOwnProperty(state, ObjectPropertyName(strings->isView),
+                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isView, builtinArrayBufferIsView, 1, NativeFunctionInfo::Strict)),
+                                                              (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayBufferPrototype = new Object(state, m_objectPrototype);
+    m_arrayBufferPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_arrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_arrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                             ObjectPropertyDescriptor(Value(strings->ArrayBuffer.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_arrayBuffer->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    JSGetterSetter gs(
+        new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinArrayBufferByteLengthGetter, 0, NativeFunctionInfo::Strict)),
+        Value(Value::EmptyValue));
+    ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+    m_arrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
+    m_arrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
+                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinArrayBufferSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_arrayBuffer->setFunctionPrototype(state, m_arrayBufferPrototype);
+
+    defineOwnProperty(state, ObjectPropertyName(strings->ArrayBuffer),
+                      ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFromSyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFromSyncIterator.cpp
new file mode 100644 (file)
index 0000000..5a81337
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/AsyncFromSyncIteratorObject.h"
+#include "runtime/PromiseObject.h"
+#include "runtime/ErrorObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+class ScriptAsyncFromSyncIteratorHelperFunctionObject : public NativeFunctionObject {
+public:
+    ScriptAsyncFromSyncIteratorHelperFunctionObject(ExecutionState& state, NativeFunctionInfo info, bool done)
+        : NativeFunctionObject(state, info)
+        , m_done(done)
+    {
+    }
+
+    bool m_done;
+};
+
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-async-from-sync-iterator-value-unwrap-functions
+static Value asyncFromSyncIteratorValueUnwrapLogic(ExecutionState& state, ScriptAsyncFromSyncIteratorHelperFunctionObject* activeFunctionObject, const Value& value)
+{
+    // Let F be the active function object.
+    ScriptAsyncFromSyncIteratorHelperFunctionObject* F = activeFunctionObject;
+    // Return ! CreateIterResultObject(value, F.[[Done]]).
+    return IteratorObject::createIterResultObject(state, value, F->m_done);
+}
+
+static Value asyncFromSyncIteratorValueUnwrap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return asyncFromSyncIteratorValueUnwrapLogic(state, (ScriptAsyncFromSyncIteratorHelperFunctionObject*)state.resolveCallee(), argv[0]);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation
+static Value asyncFromSyncIteratorContinuation(ExecutionState& state, Object* result, PromiseReaction::Capability promiseCapability)
+{
+    // Let done be IteratorComplete(result).
+    bool done;
+    try {
+        done = IteratorObject::iteratorComplete(state, result);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(done, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+    // Let value be IteratorValue(result).
+    Value value;
+    try {
+        value = IteratorObject::iteratorValue(state, result);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(value, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+    // Let valueWrapper be ? PromiseResolve(%Promise%, « value »).
+    PromiseObject* valueWrapper = nullptr;
+    try {
+        valueWrapper = PromiseObject::promiseResolve(state, state.context()->globalObject()->promise(), value)->asPromiseObject();
+    } catch (const Value& thrownValue) {
+        // * added step from 2020 (esid: language/statements/for-await-of/async-from-sync-iterator-continuation-abrupt-completion-get-constructor.js)
+        // IfAbruptRejectPromise(valueWrapper, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+
+    // Let steps be the algorithm steps defined in Async-from-Sync Iterator Value Unwrap Functions.
+    // Let onFulfilled be CreateBuiltinFunction(steps, « [[Done]] »).
+    // Set onFulfilled.[[Done]] to done.
+    auto onFulfilled = new ScriptAsyncFromSyncIteratorHelperFunctionObject(state, NativeFunctionInfo(AtomicString(), asyncFromSyncIteratorValueUnwrap, 1), done);
+    // Perform ! PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
+    valueWrapper->then(state, onFulfilled, Value(), promiseCapability);
+    // Return promiseCapability.[[Promise]].
+    return promiseCapability.m_promise;
+}
+
+static Value builtinAsyncFromSyncIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.next
+    // Let O be the this value.
+    Value& O = thisValue;
+    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
+    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
+    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
+    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
+        // Let invalidIteratorError be a newly created TypeError object.
+        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+    // Let syncIteratorRecord be O.[[SyncIteratorRecord]].
+    auto syncIteratorRecord = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord();
+    Object* result;
+    try {
+        // Let result be IteratorNext(syncIteratorRecord, value).
+        result = IteratorObject::iteratorNext(state, syncIteratorRecord, argv[0]);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(result, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
+    return asyncFromSyncIteratorContinuation(state, result, promiseCapability);
+}
+
+static Value builtinAsyncFromSyncIteratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.return
+    Value value = argv[0];
+    // Let O be the this value.
+    Value& O = thisValue;
+    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
+    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
+    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
+    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
+        // Let invalidIteratorError be a newly created TypeError object.
+        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+    // Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
+    Object* syncIterator = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord()->m_iterator;
+    // Let return be GetMethod(syncIterator, "return").
+    Value returnVariable;
+    try {
+        returnVariable = Object::getMethod(state, syncIterator, state.context()->staticStrings().stringReturn);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(return, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+
+    // If return is undefined, then
+    if (returnVariable.isUndefined()) {
+        // Let iterResult be ! CreateIterResultObject(value, true).
+        Value iterResult = IteratorObject::createIterResultObject(state, value, true);
+        // Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
+        Object::call(state, promiseCapability.m_resolveFunction, Value(), 1, &iterResult);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let result be Call(return, syncIterator, « value »).
+    Value result;
+    try {
+        result = Object::call(state, returnVariable, syncIterator, 1, &value);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(return, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+
+    // If Type(result) is not Object, then
+    if (!result.isObject()) {
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
+        Value typeError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("result of iterator is not Object"));
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &typeError);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
+    return asyncFromSyncIteratorContinuation(state, result.asObject(), promiseCapability);
+}
+
+static Value builtinAsyncFromSyncIteratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.throw
+    Value value = argv[0];
+    // Let O be the this value.
+    Value& O = thisValue;
+    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
+    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
+    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
+    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
+        // Let invalidIteratorError be a newly created TypeError object.
+        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
+    Object* syncIterator = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord()->m_iterator;
+    // Let throw be GetMethod(syncIterator, "throw").
+    Value throwVariable;
+    try {
+        throwVariable = Object::getMethod(state, syncIterator, state.context()->staticStrings().stringThrow);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(return, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+
+    // If throw is undefined, then
+    if (throwVariable.isUndefined()) {
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &value);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let result be Call(throw, syncIterator, « value »).
+    Value result;
+    try {
+        result = Object::call(state, throwVariable, syncIterator, 1, &value);
+    } catch (const Value& thrownValue) {
+        // IfAbruptRejectPromise(result, promiseCapability).
+        Value argv = thrownValue;
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
+        return promiseCapability.m_promise;
+    }
+
+    // If Type(result) is not Object, then
+    if (!result.isObject()) {
+        // Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
+        Value typeError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("result of iterator is not Object"));
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &typeError);
+        // Return promiseCapability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
+    return asyncFromSyncIteratorContinuation(state, result.asObject(), promiseCapability);
+}
+
+void GlobalObject::installAsyncFromSyncIterator(ExecutionState& state)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%-object
+    m_asyncFromSyncIteratorPrototype = new Object(state, m_asyncIteratorPrototype);
+    m_asyncFromSyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_asyncFromSyncIteratorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                        ObjectPropertyDescriptor(String::fromASCII("Async-from-Sync Iterator"), ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinAsyncFromSyncIteratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
+                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinAsyncFromSyncIteratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
+                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinAsyncFromSyncIteratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncFunction.cpp
new file mode 100644 (file)
index 0000000..4835ade
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/GeneratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ScriptAsyncFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinAsyncFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
+    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
+    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, false, true, false);
+
+    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->asyncFunctionPrototype();
+    });
+
+    return new ScriptAsyncFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
+}
+
+void GlobalObject::installAsyncFunction(ExecutionState& state)
+{
+    m_asyncFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncFunction, builtinAsyncFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_asyncFunction->setGlobalIntrinsicObject(state);
+    m_asyncFunction->setPrototype(state, m_function);
+
+    m_asyncFunctionPrototype = new Object(state, m_functionPrototype);
+    m_asyncFunctionPrototype->setGlobalIntrinsicObject(state, true);
+    m_asyncFunction->setFunctionPrototype(state, m_asyncFunctionPrototype);
+
+    m_asyncFunctionPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
+                                                ObjectPropertyDescriptor(m_asyncFunction, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_asyncFunctionPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                ObjectPropertyDescriptor(state.context()->staticStrings().AsyncFunction.string(), ObjectPropertyDescriptor::ConfigurablePresent));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncGeneratorFunction.cpp
new file mode 100644 (file)
index 0000000..612e71f
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/ScriptAsyncGeneratorFunctionObject.h"
+#include "runtime/AsyncGeneratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinAsyncGeneratorFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
+    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
+    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, true, true, false);
+
+    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->asyncGenerator();
+    });
+
+    return new ScriptAsyncGeneratorFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
+}
+
+static Value builtinAsyncGeneratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Next, argv[0]);
+}
+
+static Value builtinAsyncGeneratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Return, argv[0]);
+}
+
+static Value builtinAsyncGeneratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Throw, argv[0]);
+}
+
+void GlobalObject::installAsyncGeneratorFunction(ExecutionState& state)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asyncgeneratorfunction
+    m_asyncGeneratorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncGeneratorFunction, builtinAsyncGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_asyncGeneratorFunction->setGlobalIntrinsicObject(state);
+    m_asyncGeneratorFunction->setPrototype(state, m_function);
+
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-asyncgeneratorfunction-prototype
+    m_asyncGenerator = new Object(state, m_functionPrototype);
+    m_asyncGenerator->setGlobalIntrinsicObject(state, true);
+
+    m_asyncGeneratorFunction->setFunctionPrototype(state, m_asyncGenerator);
+
+    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
+                                        ObjectPropertyDescriptor(m_asyncGeneratorFunction, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                        ObjectPropertyDescriptor(state.context()->staticStrings().AsyncGeneratorFunction.string(), ObjectPropertyDescriptor::ConfigurablePresent));
+
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-asyncgenerator-prototype
+    m_asyncGeneratorPrototype = new Object(state, m_asyncIteratorPrototype);
+    m_asyncGeneratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().prototype), ObjectPropertyDescriptor(m_asyncGeneratorPrototype, ObjectPropertyDescriptor::ConfigurablePresent));
+    m_asyncGeneratorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_asyncGenerator, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinAsyncGeneratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
+                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinAsyncGeneratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
+                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinAsyncGeneratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                                ObjectPropertyDescriptor(Value(state.context()->staticStrings().AsyncGenerator.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAsyncIterator.cpp
new file mode 100644 (file)
index 0000000..d58c145
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinAsyncIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return thisValue;
+}
+
+void GlobalObject::installAsyncIterator(ExecutionState& state)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-object
+    m_asyncIteratorPrototype = new Object(state);
+    m_asyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asynciteratorprototype-asynciterator
+    m_asyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().asyncIterator),
+                                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.asyncIterator]")), builtinAsyncIteratorIterator, 0, NativeFunctionInfo::Strict)),
+                                                                                        (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinAtomics.cpp
new file mode 100644 (file)
index 0000000..7ea0d7c
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#if defined(ENABLE_THREADING)
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/TypedArrayObject.h"
+#include "runtime/TypedArrayInlines.h"
+#include "runtime/Global.h"
+#include "runtime/BigInt.h"
+
+#if !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) && !defined(ENABLE_ATOMICS_GLOBAL_LOCK)
+#error "without builtin atomic functions, we need to atomics global lock for implementing atomics builtin"
+#endif
+
+namespace Escargot {
+
+enum class AtomicBinaryOps : uint8_t {
+    ADD,
+    AND,
+    EXCH,
+    OR,
+    SUB,
+    XOR,
+};
+
+static ArrayBuffer* validateIntegerTypedArray(ExecutionState& state, Value typedArray, bool waitable = false)
+{
+    ArrayBuffer* buffer = TypedArrayObject::validateTypedArray(state, typedArray);
+    TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject();
+
+    if (waitable) {
+        if ((TA->typedArrayType() != TypedArrayType::Int32) && (TA->typedArrayType() != TypedArrayType::BigInt64)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+        }
+    } else if ((TA->typedArrayType() == TypedArrayType::Uint8Clamped) || (TA->typedArrayType() == TypedArrayType::Float32) || (TA->typedArrayType() == TypedArrayType::Float64)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+    }
+
+    return buffer;
+}
+
+static size_t validateAtomicAccess(ExecutionState& state, TypedArrayObject* typedArray, Value index)
+{
+    uint64_t accessIndex = index.toIndex(state);
+    size_t length = typedArray->arrayLength();
+    if (UNLIKELY(accessIndex == Value::InvalidIndexValue || accessIndex >= (uint64_t)length)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::GlobalObject_RangeError);
+    }
+
+    ASSERT(accessIndex < std::numeric_limits<size_t>::max());
+    size_t elementSize = typedArray->elementSize();
+    size_t offset = typedArray->byteOffset();
+    return (static_cast<size_t>(accessIndex) * elementSize) + offset;
+}
+
+template <typename T, typename ArgType = int64_t>
+static T atomicOperation(volatile uint8_t* rawStart, ArgType value, AtomicBinaryOps op)
+{
+    T returnValue;
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+    volatile T* ptr = reinterpret_cast<volatile T*>(rawStart);
+    switch (op) {
+    case AtomicBinaryOps::ADD:
+        returnValue = __atomic_fetch_add(ptr, value, __ATOMIC_SEQ_CST);
+        break;
+    case AtomicBinaryOps::AND:
+        returnValue = __atomic_fetch_and(ptr, value, __ATOMIC_SEQ_CST);
+        break;
+    case AtomicBinaryOps::EXCH: {
+        T v = value;
+        __atomic_exchange(ptr, &v, &returnValue, __ATOMIC_SEQ_CST);
+    } break;
+    case AtomicBinaryOps::OR:
+        returnValue = __atomic_fetch_or(ptr, value, __ATOMIC_SEQ_CST);
+        break;
+    case AtomicBinaryOps::SUB:
+        returnValue = __atomic_fetch_sub(ptr, value, __ATOMIC_SEQ_CST);
+        break;
+    default:
+        ASSERT(op == AtomicBinaryOps::XOR);
+        returnValue = __atomic_fetch_xor(ptr, value, __ATOMIC_SEQ_CST);
+        break;
+    }
+#else
+    {
+        volatile T* ptr = reinterpret_cast<volatile T*>(rawStart);
+        std::lock_guard<SpinLock> guard(Global::atomicsLock());
+        returnValue = *ptr;
+        switch (op) {
+        case AtomicBinaryOps::ADD:
+            *ptr = *ptr + value;
+            break;
+        case AtomicBinaryOps::AND:
+            *ptr = *ptr & value;
+            break;
+        case AtomicBinaryOps::EXCH:
+            *ptr = value;
+            break;
+        case AtomicBinaryOps::OR:
+            *ptr = *ptr | value;
+            break;
+        case AtomicBinaryOps::SUB:
+            *ptr = *ptr - value;
+            break;
+        default:
+            ASSERT(op == AtomicBinaryOps::XOR);
+            *ptr = *ptr ^ value;
+            break;
+        }
+    }
+#endif
+    return returnValue;
+}
+
+static Value getModifySetValueInBuffer(ExecutionState& state, ArrayBuffer* buffer, size_t indexedPosition, TypedArrayType type, Value v2, AtomicBinaryOps op)
+{
+    size_t elemSize = TypedArrayHelper::elementSize(type);
+    ASSERT(indexedPosition + elemSize <= buffer->byteLength());
+    uint8_t* rawStart = const_cast<uint8_t*>(buffer->data()) + indexedPosition;
+
+    if (v2.isInt32()) {
+        switch (type) {
+        case TypedArrayType::Int8:
+            return Value(atomicOperation<int8_t>(rawStart, v2.asInt32(), op));
+        case TypedArrayType::Int16:
+            return Value(atomicOperation<int16_t>(rawStart, v2.asInt32(), op));
+        case TypedArrayType::Int32:
+            return Value(atomicOperation<int32_t>(rawStart, v2.asInt32(), op));
+        case TypedArrayType::Uint8:
+            return Value(atomicOperation<uint8_t>(rawStart, v2.asInt32(), op));
+        case TypedArrayType::Uint16:
+            return Value(atomicOperation<uint16_t>(rawStart, v2.asInt32(), op));
+        case TypedArrayType::Uint32:
+            return Value(atomicOperation<uint32_t>(rawStart, v2.asInt32(), op));
+        default:
+            ASSERT(TypedArrayType::Uint8Clamped == type);
+            return Value(atomicOperation<uint8_t>(rawStart, v2.asInt32(), op));
+        }
+    }
+
+    switch (type) {
+    case TypedArrayType::Int8:
+        return Value(atomicOperation<int8_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Int16:
+        return Value(atomicOperation<int16_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Int32:
+        return Value(atomicOperation<int32_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Uint8:
+        return Value(atomicOperation<uint8_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Uint16:
+        return Value(atomicOperation<uint16_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Uint32:
+        return Value(atomicOperation<uint32_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::Uint8Clamped:
+        return Value(atomicOperation<uint8_t, int64_t>(rawStart, v2.asNumber(), op));
+    case TypedArrayType::BigInt64:
+        return new BigInt(atomicOperation<int64_t, int64_t>(rawStart, v2.asBigInt()->toInt64(), op));
+    default:
+        ASSERT(TypedArrayType::BigUint64 == type);
+        return new BigInt(atomicOperation<uint64_t, uint64_t>(rawStart, v2.asBigInt()->toUint64(), op));
+    }
+}
+
+static Value atomicReadModifyWrite(ExecutionState& state, Value typedArray, Value index, Value value, AtomicBinaryOps op)
+{
+    ArrayBuffer* buffer = validateIntegerTypedArray(state, typedArray);
+    TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject();
+    size_t indexedPosition = validateAtomicAccess(state, TA, index);
+    TypedArrayType type = TA->typedArrayType();
+
+    Value v;
+    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
+        v = value.toBigInt(state);
+    } else {
+        v = Value(value.toInteger(state));
+    }
+
+    return getModifySetValueInBuffer(state, buffer, indexedPosition, type, v, op);
+}
+
+static Value builtinAtomicsAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::ADD);
+}
+
+static Value builtinAtomicsAnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::AND);
+}
+
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+template <typename T>
+void atomicCompareExchange(uint8_t* rawStart, uint8_t* expectedBytes, uint8_t* replacementBytes)
+{
+    __atomic_compare_exchange(reinterpret_cast<T*>(rawStart), reinterpret_cast<T*>(expectedBytes),
+                              reinterpret_cast<T*>(replacementBytes), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+#endif
+
+static Value builtinAtomicsCompareExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]);
+    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
+    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
+    TypedArrayType type = TA->typedArrayType();
+
+    Value expected;
+    Value replacement;
+    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
+        expected = argv[2].toBigInt(state);
+        replacement = argv[3].toBigInt(state);
+    } else {
+        expected = Value(argv[2].toInteger(state));
+        replacement = Value(argv[3].toInteger(state));
+    }
+
+    size_t elemSize = TypedArrayHelper::elementSize(type);
+    ASSERT(indexedPosition + elemSize <= buffer->byteLength());
+    uint8_t* expectedBytes = ALLOCA(8, uint8_t, state);
+    TypedArrayHelper::numberToRawBytes(state, type, expected, expectedBytes);
+    uint8_t* rawStart = const_cast<uint8_t*>(buffer->data()) + indexedPosition;
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+    uint8_t* replacementBytes = ALLOCA(8, uint8_t, state);
+    TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes);
+    bool ret;
+    switch (type) {
+    case TypedArrayType::Int8:
+        atomicCompareExchange<int8_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Int16:
+        atomicCompareExchange<int16_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Int32:
+        atomicCompareExchange<int32_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Uint8:
+        atomicCompareExchange<uint8_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Uint16:
+        atomicCompareExchange<uint16_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Uint32:
+        atomicCompareExchange<uint32_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::Uint8Clamped:
+        atomicCompareExchange<uint8_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    case TypedArrayType::BigInt64:
+        atomicCompareExchange<int64_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    default:
+        ASSERT(TypedArrayType::BigUint64 == type);
+        atomicCompareExchange<uint64_t>(rawStart, expectedBytes, replacementBytes);
+        break;
+    }
+    return TypedArrayHelper::rawBytesToNumber(state, type, expectedBytes);
+#else
+    std::lock_guard<SpinLock> guard(Global::atomicsLock());
+    Value rawBytesRead = TypedArrayHelper::rawBytesToNumber(state, type, rawStart);
+
+    bool isByteListEqual = true;
+    for (size_t i = 0; i < elemSize; i++) {
+        if (rawStart[i] != expectedBytes[i]) {
+            isByteListEqual = false;
+            break;
+        }
+    }
+    if (isByteListEqual) {
+        uint8_t* replacementBytes = ALLOCA(8, uint8_t, state);
+        TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes);
+        memcpy(rawStart, replacementBytes, elemSize);
+    }
+    return rawBytesRead;
+#endif
+}
+
+static Value builtinAtomicsExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::EXCH);
+}
+
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+template <typename T>
+void atomicLoad(uint8_t* rawStart, uint8_t* rawBytes)
+{
+    __atomic_load(reinterpret_cast<T*>(rawStart), reinterpret_cast<T*>(rawBytes), __ATOMIC_SEQ_CST);
+}
+#endif
+
+static Value builtinAtomicsLoad(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]);
+    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
+    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
+    TypedArrayType type = TA->typedArrayType();
+
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+    uint8_t* rawStart = TA->buffer()->data() + indexedPosition;
+    uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
+    switch (type) {
+    case TypedArrayType::Int8:
+        atomicLoad<int8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Int16:
+        atomicLoad<int16_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Int32:
+        atomicLoad<int32_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint8:
+        atomicLoad<uint8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint16:
+        atomicLoad<uint16_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint32:
+        atomicLoad<uint32_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint8Clamped:
+        atomicLoad<uint8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::BigInt64:
+        atomicLoad<int64_t>(rawStart, rawBytes);
+        break;
+    default:
+        ASSERT(TypedArrayType::BigUint64 == type);
+        atomicLoad<uint64_t>(rawStart, rawBytes);
+        break;
+    }
+    return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes);
+#else
+    std::lock_guard<SpinLock> guard(Global::atomicsLock());
+    return buffer->getValueFromBuffer(state, indexedPosition, type);
+#endif
+}
+
+static Value builtinAtomicsOr(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::OR);
+}
+
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+template <typename T>
+void atomicStore(uint8_t* rawStart, uint8_t* rawBytes)
+{
+    __atomic_store(reinterpret_cast<T*>(rawStart), reinterpret_cast<T*>(rawBytes), __ATOMIC_SEQ_CST);
+}
+#endif
+
+static Value builtinAtomicsStore(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0]);
+    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
+    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
+    TypedArrayType type = TA->typedArrayType();
+
+    Value value = argv[2];
+    Value v;
+    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
+        v = value.toBigInt(state);
+    } else {
+        v = Value(value.toInteger(state));
+    }
+
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+    uint8_t* rawStart = TA->buffer()->data() + indexedPosition;
+    uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
+    TypedArrayHelper::numberToRawBytes(state, type, v, rawBytes);
+
+    switch (type) {
+    case TypedArrayType::Int8:
+        atomicStore<int8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Int16:
+        atomicStore<int16_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Int32:
+        atomicStore<int32_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint8:
+        atomicStore<uint8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint16:
+        atomicStore<uint16_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint32:
+        atomicStore<uint32_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::Uint8Clamped:
+        atomicStore<uint8_t>(rawStart, rawBytes);
+        break;
+    case TypedArrayType::BigInt64:
+        atomicStore<int64_t>(rawStart, rawBytes);
+        break;
+    default:
+        ASSERT(TypedArrayType::BigUint64 == type);
+        atomicStore<uint64_t>(rawStart, rawBytes);
+        break;
+    }
+    return v;
+#else
+    std::lock_guard<SpinLock> guard(Global::atomicsLock());
+    buffer->setValueInBuffer(state, indexedPosition, type, v);
+    return v;
+#endif
+}
+
+static Value builtinAtomicsSub(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::SUB);
+}
+
+static Value builtinAtomicsXor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::XOR);
+}
+
+void GlobalObject::installAtomics(ExecutionState& state)
+{
+    m_atomics = new Object(state);
+    m_atomics->setGlobalIntrinsicObject(state);
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                ObjectPropertyDescriptor(Value(state.context()->staticStrings().Atomics.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinAtomicsAdd, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringAnd),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringAnd, builtinAtomicsAnd, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().compareExchange),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().compareExchange, builtinAtomicsCompareExchange, 4, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().exchange),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().exchange, builtinAtomicsExchange, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().load),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().load, builtinAtomicsLoad, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringOr),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringOr, builtinAtomicsOr, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().store),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().store, builtinAtomicsStore, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sub),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sub, builtinAtomicsSub, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringXor),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringXor, builtinAtomicsXor, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Atomics),
+                      ObjectPropertyDescriptor(m_atomics, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBigInt.cpp
new file mode 100644 (file)
index 0000000..c0a27e4
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/ThreadLocal.h"
+#include "runtime/VMInstance.h"
+#include "runtime/BigIntObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+#include "intl/IntlNumberFormat.h"
+#endif
+
+namespace Escargot {
+
+static Value builtinBigIntConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is not undefined, throw a TypeError exception.
+    if (newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "illegal constructor BigInt");
+    }
+    // Let prim be ? ToPrimitive(value, hint Number).
+    Value prim = argv[0].toPrimitive(state, Value::PreferNumber);
+    // If Type(prim) is Number, return ? NumberToBigInt(prim).
+    if (prim.isNumber()) {
+        // NumberToBigInt(prim)
+        // If IsInteger(number) is false, throw a RangeError exception.
+        if (!prim.isInteger(state)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The value you input to BigInt constructor is not integer");
+        }
+        double numValue = prim.asNumber();
+        if ((numValue > (double)std::numeric_limits<int64_t>::max()) || (numValue < (double)std::numeric_limits<int64_t>::min())) {
+            // handle overflowed integer number
+            bf_t r;
+            bf_init(ThreadLocal::bfContext(), &r);
+            int ret = bf_set_float64(&r, numValue);
+            ASSERT(!ret);
+            ASSERT(bf_is_finite(&r));
+
+            return new BigInt(r);
+        }
+        // Return the BigInt value that represents the mathematical value of number.
+        return new BigInt((int64_t)numValue);
+    } else {
+        // Otherwise, return ? ToBigInt(value).
+        return argv[0].toBigInt(state);
+    }
+}
+
+static Value builtinBigIntAsUintN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let bits be ? ToIndex(bits).
+    auto bits = argv[0].toIndex(state);
+    if (bits == Value::InvalidIndexValue) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::CanNotConvertValueToIndex);
+    }
+    // Let bigint be ? ToBigInt(bigint).
+    BigInt* bigint = argv[1].toBigInt(state);
+    // Return a BigInt representing bigint modulo 2bits.
+    bf_t mask, r;
+    bf_init(ThreadLocal::bfContext(), &mask);
+    bf_init(ThreadLocal::bfContext(), &r);
+    bf_set_ui(&mask, 1);
+    bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
+    bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ);
+    bf_logic_and(&r, bigint->bf(), &mask);
+    bf_delete(&mask);
+
+    return new BigInt(r);
+}
+
+static Value builtinBigIntAsIntN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let bits be ? ToIndex(bits).
+    auto bits = argv[0].toIndex(state);
+    if (bits == Value::InvalidIndexValue) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::CanNotConvertValueToIndex);
+    }
+    // Let bigint be ? ToBigInt(bigint).
+    BigInt* bigint = argv[1].toBigInt(state);
+    // Return a BigInt representing bigint modulo 2bits.
+    bf_t mask, r;
+    bf_init(ThreadLocal::bfContext(), &mask);
+    bf_init(ThreadLocal::bfContext(), &r);
+    bf_set_ui(&mask, 1);
+    bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
+    bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ);
+    bf_logic_and(&r, bigint->bf(), &mask);
+    if (bits != 0) {
+        bf_set_ui(&mask, 1);
+        bf_mul_2exp(&mask, bits - 1, BF_PREC_INF, BF_RNDZ);
+        if (bf_cmpu(&r, &mask) >= 0) {
+            bf_set_ui(&mask, 1);
+            bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
+            bf_sub(&r, &r, &mask, BF_PREC_INF, BF_RNDZ);
+        }
+    }
+    bf_delete(&mask);
+
+    return new BigInt(r);
+}
+
+// The abstract operation thisBigIntValue(value) performs the following steps:
+// If Type(value) is BigInt, return value.
+// If Type(value) is Object and value has a [[BigIntData]] internal slot, then
+// Assert: Type(value.[[BigIntData]]) is BigInt.
+// Return value.[[BigIntData]].
+// Throw a TypeError exception.
+#define RESOLVE_THIS_BINDING_TO_BIGINT(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                           \
+    BigInt* NAME = nullptr;                                                                                                                                                                                                                                  \
+    if (thisValue.isObject()) {                                                                                                                                                                                                                              \
+        if (!thisValue.asObject()->isBigIntObject()) {                                                                                                                                                                                                       \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+        }                                                                                                                                                                                                                                                    \
+        NAME = thisValue.asObject()->asBigIntObject()->primitiveValue();                                                                                                                                                                                     \
+    } else if (thisValue.isBigInt()) {                                                                                                                                                                                                                       \
+        NAME = thisValue.asBigInt();                                                                                                                                                                                                                         \
+    } else {                                                                                                                                                                                                                                                 \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);     \
+        return Value();                                                                                                                                                                                                                                      \
+    }
+
+static Value builtinBigIntToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_BIGINT(S, BigInt, toString);
+
+    double radix = 10;
+    if (argc > 0 && !argv[0].isUndefined()) {
+        radix = argv[0].toInteger(state);
+        if (radix < 2 || radix > 36) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_RadixInvalidRange);
+        }
+    }
+
+    return S->toString(radix);
+}
+
+static Value builtinBigIntValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_BIGINT(S, BigInt, valueOf);
+    return Value(S);
+}
+
+static Value builtinBigIntToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_BIGINT(thisObject, BigInt, toLocaleString);
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    Value locales = argc > 0 ? argv[0] : Value();
+    Value options = argc > 1 ? argv[1] : Value();
+    Object* numberFormat = IntlNumberFormat::create(state, state.context(), locales, options);
+    auto result = IntlNumberFormat::format(state, numberFormat, thisObject->toString());
+
+    return new UTF16String(result.data(), result.length());
+#else
+
+    ObjectGetResult toStrFuncGetResult = state.context()->globalObject()->bigIntProxyObject()->get(state, ObjectPropertyName(state.context()->staticStrings().toString));
+    if (toStrFuncGetResult.hasValue()) {
+        Value toStrFunc = toStrFuncGetResult.value(state, thisObject);
+        if (toStrFunc.isCallable()) {
+            // toLocaleString() ignores the first argument, unlike toString()
+            return Object::call(state, toStrFunc, thisObject, 0, argv);
+        }
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().BigInt.string(), true, state.context()->staticStrings().toLocaleString.string(), ErrorObject::Messages::GlobalObject_ToLocaleStringNotCallable);
+    RELEASE_ASSERT_NOT_REACHED();
+    return Value();
+#endif
+}
+
+void GlobalObject::installBigInt(ExecutionState& state)
+{
+    m_bigInt = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().BigInt, builtinBigIntConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_bigInt->setGlobalIntrinsicObject(state);
+
+    m_bigInt->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().asUintN),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asUintN, builtinBigIntAsUintN, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigInt->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().asIntN),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asIntN, builtinBigIntAsIntN, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigIntPrototype = new Object(state);
+    m_bigIntPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigIntPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                        ObjectPropertyDescriptor(state.context()->staticStrings().BigInt.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinBigIntToString, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinBigIntValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_bigIntPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinBigIntToLocaleString, 0, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    m_bigInt->setFunctionPrototype(state, m_bigIntPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().BigInt),
+                      ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinBoolean.cpp
new file mode 100644 (file)
index 0000000..1a07a2f
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/BooleanObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinBooleanConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    bool primitiveVal = argv[0].toBoolean(state);
+    if (!newTarget.hasValue()) {
+        return Value(primitiveVal);
+    } else {
+        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+            return constructorRealm->globalObject()->booleanPrototype();
+        });
+        BooleanObject* boolObj = new BooleanObject(state, proto, primitiveVal);
+        return boolObj;
+    }
+}
+
+static Value builtinBooleanValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isBoolean()) {
+        return Value(thisValue);
+    } else if (thisValue.isObject() && thisValue.asObject()->isBooleanObject()) {
+        return Value(thisValue.asPointerValue()->asBooleanObject()->primitiveValue());
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotBoolean);
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static Value builtinBooleanToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isBoolean()) {
+        return Value(thisValue.toString(state));
+    } else if (thisValue.isObject() && thisValue.asObject()->isBooleanObject()) {
+        return Value(thisValue.asPointerValue()->asBooleanObject()->primitiveValue()).toString(state);
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotBoolean);
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void GlobalObject::installBoolean(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_boolean = new NativeFunctionObject(state, NativeFunctionInfo(strings->Boolean, builtinBooleanConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_boolean->setGlobalIntrinsicObject(state);
+
+    m_booleanPrototype = new BooleanObject(state, m_objectPrototype, false);
+    m_booleanPrototype->setGlobalIntrinsicObject(state, true);
+    m_booleanPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.3.3.2 Boolean.prototype.toString
+    m_booleanPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinBooleanToString, 0, NativeFunctionInfo::Strict)),
+                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $19.3.3.3 Boolean.prototype.valueOf
+    m_booleanPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinBooleanValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_boolean->setFunctionPrototype(state, m_booleanPrototype);
+
+    defineOwnProperty(state, ObjectPropertyName(strings->Boolean),
+                      ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDataView.cpp
new file mode 100644 (file)
index 0000000..5ca74af
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/DataViewObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+#define FOR_EACH_DATAVIEW_TYPES(F) \
+    F(Float32)                     \
+    F(Float64)                     \
+    F(Int8)                        \
+    F(Int16)                       \
+    F(Int32)                       \
+    F(Uint8)                       \
+    F(Uint16)                      \
+    F(Uint32)                      \
+    F(BigInt64)                    \
+    F(BigUint64)
+
+static Value builtinDataViewConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+    if (!(argv[0].isObject() && argv[0].asPointerValue()->isArrayBuffer())) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotArrayBufferObject);
+    }
+
+    ArrayBuffer* buffer = argv[0].asObject()->asArrayBuffer();
+    double byteOffset = 0;
+    if (argc >= 2) {
+        Value& val = argv[1];
+        byteOffset = val.toIndex(state);
+        if (byteOffset == Value::InvalidIndexValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+        }
+    }
+    if (buffer->isDetachedBuffer()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, "%s: ArrayBuffer is detached buffer");
+    }
+    double bufferByteLength = buffer->byteLength();
+
+    if (byteOffset > bufferByteLength) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+    }
+    double byteLength = bufferByteLength - byteOffset;
+
+    if (argc >= 3) {
+        Value& val = argv[2];
+        if (!val.isUndefined()) {
+            byteLength = val.toIndex(state);
+            if (byteOffset + byteLength > bufferByteLength || byteLength == Value::InvalidIndexValue) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+            }
+        }
+    }
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->dataViewPrototype();
+    });
+    ArrayBufferView* obj = new DataViewObject(state, proto);
+    obj->setBuffer(buffer, byteOffset, byteLength);
+
+    if (obj->buffer()->isDetachedBuffer()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_DetachedBuffer);
+    }
+
+    return obj;
+}
+
+#define DECLARE_DATAVIEW_GETTER(Name)                                                                                                    \
+    static Value builtinDataViewGet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                    \
+        RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, DataView, get##Name);                                                                 \
+        if (!(thisObject->isDataViewObject())) {                                                                                         \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(),            \
+                                           true, state.context()->staticStrings().get##Name.string(),                                    \
+                                           ErrorObject::Messages::GlobalObject_ThisNotDataViewObject);                                   \
+        }                                                                                                                                \
+        if (argc < 2) {                                                                                                                  \
+            return thisObject->asDataViewObject()->getViewValue(state, argv[0], Value(false), TypedArrayType::Name);                     \
+        } else {                                                                                                                         \
+            return thisObject->asDataViewObject()->getViewValue(state, argv[0], argv[1], TypedArrayType::Name);                          \
+        }                                                                                                                                \
+    }
+
+#define DECLARE_DATAVIEW_SETTER(Name)                                                                                                    \
+    static Value builtinDataViewSet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                    \
+        RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, DataView, get##Name);                                                                 \
+        if (!(thisObject->isDataViewObject())) {                                                                                         \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(),            \
+                                           true, state.context()->staticStrings().set##Name.string(),                                    \
+                                           ErrorObject::Messages::GlobalObject_ThisNotDataViewObject);                                   \
+        }                                                                                                                                \
+        if (argc < 3) {                                                                                                                  \
+            return thisObject->asDataViewObject()->setViewValue(state, argv[0], Value(false), TypedArrayType::Name, argv[1]);            \
+        } else {                                                                                                                         \
+            return thisObject->asDataViewObject()->setViewValue(state, argv[0], argv[2], TypedArrayType::Name, argv[1]);                 \
+        }                                                                                                                                \
+    }
+
+FOR_EACH_DATAVIEW_TYPES(DECLARE_DATAVIEW_GETTER);
+FOR_EACH_DATAVIEW_TYPES(DECLARE_DATAVIEW_SETTER);
+
+static Value builtinDataViewBufferGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject())) {
+        ArrayBuffer* buffer = thisValue.asObject()->asArrayBufferView()->buffer();
+        if (buffer) {
+            return Value(buffer);
+        }
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.buffer called on incompatible receiver");
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static Value builtinDataViewByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject() && thisValue.asObject()->asDataViewObject()->buffer() && !thisValue.asObject()->asDataViewObject()->buffer()->isDetachedBuffer())) {
+        return Value(thisValue.asObject()->asArrayBufferView()->byteLength());
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.byteLength called on incompatible receiver");
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static Value builtinDataViewByteOffsetGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject() && thisValue.asObject()->asDataViewObject()->buffer() && !thisValue.asObject()->asDataViewObject()->buffer()->isDetachedBuffer())) {
+        return Value(thisValue.asObject()->asArrayBufferView()->byteOffset());
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.byteOffset called on incompatible receiver");
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void GlobalObject::installDataView(ExecutionState& state)
+{
+    m_dataView = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().DataView, builtinDataViewConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_dataView->setGlobalIntrinsicObject(state);
+
+    m_dataViewPrototype = new DataViewObject(state, m_objectPrototype);
+    m_dataViewPrototype->setGlobalIntrinsicObject(state, true);
+    m_dataView->setFunctionPrototype(state, m_dataViewPrototype);
+
+    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_dataViewPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                          ObjectPropertyDescriptor(Value(state.context()->staticStrings().DataView.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+#define DATAVIEW_DEFINE_GETTER(Name)                                                                                                                                                                                          \
+    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##Name),                                                                                                             \
+                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get##Name, builtinDataViewGet##Name, 1, NativeFunctionInfo::Strict)), \
+                                                                    (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+#define DATAVIEW_DEFINE_SETTER(Name)                                                                                                                                                                                          \
+    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().set##Name),                                                                                                             \
+                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set##Name, builtinDataViewSet##Name, 2, NativeFunctionInfo::Strict)), \
+                                                                    (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    FOR_EACH_DATAVIEW_TYPES(DATAVIEW_DEFINE_GETTER);
+    FOR_EACH_DATAVIEW_TYPES(DATAVIEW_DEFINE_SETTER);
+
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getBuffer, builtinDataViewBufferGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor bufferDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->buffer), bufferDesc);
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinDataViewByteLengthGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteOffset, builtinDataViewByteOffsetGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor byteOffsetDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteOffset), byteOffsetDesc);
+    }
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().DataView),
+                      ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinDate.cpp
new file mode 100644 (file)
index 0000000..6ccfc5f
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/DateObject.h"
+#include "runtime/ErrorObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+#include "intl/IntlDateTimeFormat.h"
+#endif
+
+namespace Escargot {
+
+#define FOR_EACH_DATE_VALUES(F)                     \
+    /* Name, DateSetterTypr, Setter length, UTC? */ \
+    F(Milliseconds, Time, 1, false)                 \
+    F(UTCMilliseconds, Time, 1, true)               \
+    F(Seconds, Time, 2, false)                      \
+    F(UTCSeconds, Time, 2, true)                    \
+    F(Minutes, Time, 3, false)                      \
+    F(UTCMinutes, Time, 3, true)                    \
+    F(Hours, Time, 4, false)                        \
+    F(UTCHours, Time, 4, true)                      \
+    F(Date, Day, 1, false)                          \
+    F(UTCDate, Day, 1, true)                        \
+    F(Month, Day, 2, false)                         \
+    F(UTCMonth, Day, 2, true)                       \
+    F(FullYear, Day, 3, false)                      \
+    F(UTCFullYear, Day, 3, true)
+
+
+bool isInValidRange(double year, double month, double date, double hour, double minute, double second, double millisecond)
+{
+    if (std::isnan(year) || std::isnan(month) || std::isnan(date) || std::isnan(hour) || std::isnan(minute) || std::isnan(second) || std::isnan(millisecond)) {
+        return false;
+    }
+    if (std::isinf(year) || std::isinf(month) || std::isinf(date) || std::isinf(hour) || std::isinf(minute) || std::isinf(second) || std::isinf(millisecond)) {
+        return false;
+    }
+
+    int32_t max32 = std::numeric_limits<int32_t>::max();
+    int64_t max64 = std::numeric_limits<int64_t>::max();
+    if (std::abs(year) > max32 || std::abs(month) > max32 || std::abs(date) > max32
+        || std::abs(hour) > max32 || std::abs(minute) > max32 || std::abs(second) > max64 || std::abs(millisecond) > max64) {
+        return false;
+    }
+    return true;
+}
+
+static Value builtinDateConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        DateObject d(state);
+        d.setTimeValue(DateObject::currentTime());
+        return d.toFullString(state);
+    } else {
+        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+            return constructorRealm->globalObject()->datePrototype();
+        });
+        DateObject* thisObject = new DateObject(state, proto);
+
+        if (argc == 0) {
+            thisObject->setTimeValue(DateObject::currentTime());
+        } else if (argc == 1) {
+            // https://www.ecma-international.org/ecma-262/6.0/#sec-date-value
+            Value v = argv[0];
+            // If Type(value) is Object and value has a [[DateValue]] internal slot, then
+            if (v.isObject() && v.asObject()->isDateObject()) {
+                // Let tv be thisTimeValue(value).
+                thisObject->setTimeValue(v.asObject()->asDateObject()->primitiveValue());
+                // Else
+            } else {
+                // Let v be ToPrimitive(value).
+                v = v.toPrimitive(state);
+                // If Type(v) is String, then
+                if (v.isString()) {
+                    thisObject->setTimeValue(state, v);
+                } else {
+                    // Let tv be ToNumber(v).
+                    double V = v.toNumber(state);
+                    thisObject->setTimeValue(DateObject::timeClip(state, V));
+                }
+            }
+        } else {
+            // https://www.ecma-international.org/ecma-262/6.0/#sec-date-year-month-date-hours-minutes-seconds-ms
+            // Assert: numberOfArgs ≥ 2.
+            ASSERT(argc > 1);
+            double args[7] = { 0, 0, 1, 0, 0, 0, 0 }; // default value of year, month, date, hour, minute, second, millisecond
+            argc = (argc > 7) ? 7 : argc; // trim arguments so that they don't corrupt stack
+            for (size_t i = 0; i < argc; i++) {
+                args[i] = argv[i].toNumber(state);
+            }
+            double year = args[0];
+            double month = args[1];
+            double date = args[2];
+            double hour = args[3];
+            double minute = args[4];
+            double second = args[5];
+            double millisecond = args[6];
+            if ((int)year >= 0 && (int)year <= 99) {
+                year += 1900;
+            }
+            if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
+                thisObject->setTimeValueAsNaN();
+            } else {
+                thisObject->setTimeValue(state, (int)year, (int)month, (int)date, (int)hour, (int)minute, second, millisecond);
+            }
+        }
+        return thisObject;
+    }
+}
+
+static Value builtinDateNow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return Value(DateObject::currentTime());
+}
+
+static Value builtinDateParse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value str = argv[0].toPrimitive(state, Value::PreferString);
+    if (str.isString()) {
+        DateObject d(state);
+        d.setTimeValue(state, str);
+        return Value(d.primitiveValue());
+    }
+    return Value(std::numeric_limits<double>::quiet_NaN());
+}
+
+static Value builtinDateUTC(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    DateObject d(state);
+    double args[7] = { std::numeric_limits<double>::quiet_NaN(), 0, 1, 0, 0, 0, 0 }; // default value of year, month, date, hour, minute, second, millisecond
+    argc = (argc > 7) ? 7 : argc; // trim arguments so that they don't corrupt stack
+    for (size_t i = 0; i < argc; i++) {
+        args[i] = argv[i].toNumber(state);
+    }
+    double year = args[0];
+    double month = args[1];
+    double date = args[2];
+    double hour = args[3];
+    double minute = args[4];
+    double second = args[5];
+    double millisecond = args[6];
+
+    if (!std::isnan(year)) {
+        int yi = (int)year;
+        if (yi >= 0 && yi <= 99) {
+            yi += 1900;
+            year = yi;
+        }
+    }
+
+    if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
+        d.setTimeValueAsNaN();
+    } else {
+        d.setTimeValue(state, year, month, date, hour, minute, second, millisecond, false);
+    }
+    return Value(d.primitiveValue());
+}
+
+#define RESOLVE_THIS_BINDING_TO_DATE(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                              \
+    if (!thisValue.isObject() || !thisValue.asObject()->isDateObject()) {                                                                                                                                                                     \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_ThisNotDateObject); \
+    }                                                                                                                                                                                                                                         \
+    DateObject* NAME = thisValue.asObject()->asDateObject();
+
+static Value builtinDateGetTime(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getTime);
+    return Value(thisObject->primitiveValue());
+}
+
+static Value builtinDateValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, valueOf);
+    double val = thisObject->primitiveValue();
+    return Value(val);
+}
+
+static Value builtinDateToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+    return thisObject->toFullString(state);
+}
+
+static Value builtinDateToDateString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+    return thisObject->toDateString(state);
+}
+
+static Value builtinDateToTimeString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+    return thisObject->toTimeString(state);
+}
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+#define INTL_DATE_TIME_FORMAT_FORMAT(REQUIRED, DEFUALT)                                                                                   \
+    double x = thisObject->primitiveValue();                                                                                              \
+    if (std::isnan(x)) {                                                                                                                  \
+        return new ASCIIString("Invalid Date");                                                                                           \
+    }                                                                                                                                     \
+    Value locales, options;                                                                                                               \
+    if (argc >= 1) {                                                                                                                      \
+        locales = argv[0];                                                                                                                \
+    }                                                                                                                                     \
+    if (argc >= 2) {                                                                                                                      \
+        options = argv[1];                                                                                                                \
+    }                                                                                                                                     \
+    auto dateTimeOption = IntlDateTimeFormat::toDateTimeOptions(state, options, String::fromASCII(REQUIRED), String::fromASCII(DEFUALT)); \
+    Object* dateFormat = IntlDateTimeFormat::create(state, state.context(), locales, dateTimeOption);                                     \
+    auto result = IntlDateTimeFormat::format(state, dateFormat, x);                                                                       \
+    return new UTF16String(result.data(), result.length());
+#endif
+
+static Value builtinDateToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    INTL_DATE_TIME_FORMAT_FORMAT("any", "all")
+#else
+    return thisObject->toLocaleFullString(state);
+#endif
+}
+
+static Value builtinDateToLocaleDateString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    INTL_DATE_TIME_FORMAT_FORMAT("date", "date")
+#else
+    return thisObject->toLocaleDateString(state);
+#endif
+}
+
+static Value builtinDateToLocaleTimeString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    INTL_DATE_TIME_FORMAT_FORMAT("time", "time")
+#else
+    return thisObject->toLocaleTimeString(state);
+#endif
+}
+
+static Value builtinDateToUTCString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toUTCString);
+    return thisObject->toUTCString(state, state.context()->staticStrings().toUTCString.string());
+}
+
+static Value builtinDateToISOString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toISOString);
+    return thisObject->toISOString(state);
+}
+
+static Value builtinDateToJSON(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Date, toJSON);
+
+    Value tv = Value(thisObject).toPrimitive(state, Value::PreferNumber);
+    if (tv.isNumber() && (std::isnan(tv.asNumber()) || std::isinf(tv.asNumber()))) {
+        return Value(Value::Null);
+    }
+
+    Value isoFunc = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toISOString)).value(state, thisObject);
+    return Object::call(state, isoFunc, thisObject, 0, nullptr);
+}
+
+#define DECLARE_STATIC_DATE_GETTER(Name, unused1, unused2, unused3)                                                                  \
+    static Value builtinDateGet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                \
+        RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, get##Name);                                                                   \
+        if (!(thisObject->isValid()))                                                                                                \
+            return Value(std::numeric_limits<double>::quiet_NaN());                                                                  \
+        return Value(thisObject->get##Name(state));                                                                                  \
+    }
+
+FOR_EACH_DATE_VALUES(DECLARE_STATIC_DATE_GETTER);
+DECLARE_STATIC_DATE_GETTER(Day, -, -, -);
+DECLARE_STATIC_DATE_GETTER(UTCDay, -, -, -);
+
+enum DateSetterType : unsigned {
+    Time,
+    Day
+};
+
+static Value builtinDateSetHelper(ExecutionState& state, DateSetterType setterType, size_t length, bool utc, Value thisValue, size_t argc, Value* argv, const AtomicString& name)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, name);
+    DateObject* d = thisObject;
+
+    if (setterType == DateSetterType::Day && length == 3) {
+        // setFullYear, setUTCFullYear case
+        if (!(d->isValid())) {
+            d->setTimeValue(DateObject::timeClip(state, 0));
+            d->setTimeValue(d->getTimezoneOffset(state) * const_Date_msPerMinute);
+        }
+        ASSERT(d->isValid());
+    }
+
+    if (argc < 1) {
+        d->setTimeValueAsNaN();
+        return Value(d->primitiveValue());
+    }
+
+    double year = 0, month = 0, date = 0, hour = 0, minute = 0, second = 0, millisecond = 0;
+
+    if (d->isValid()) {
+        if (!utc) {
+            year = d->getFullYear(state);
+            month = d->getMonth(state);
+            date = d->getDate(state);
+
+            hour = d->getHours(state);
+            minute = d->getMinutes(state);
+            second = d->getSeconds(state);
+            millisecond = d->getMilliseconds(state);
+        } else {
+            year = d->getUTCFullYear(state);
+            month = d->getUTCMonth(state);
+            date = d->getUTCDate(state);
+
+            hour = d->getUTCHours(state);
+            minute = d->getUTCMinutes(state);
+            second = d->getUTCSeconds(state);
+            millisecond = d->getUTCMilliseconds(state);
+        }
+    }
+
+    bool convertToUTC = !utc;
+
+    switch (setterType) {
+    case DateSetterType::Day:
+        if ((length >= 3) && (argc > length - 3))
+            year = argv[length - 3].toNumber(state);
+        if ((length >= 2) && (argc > length - 2))
+            month = argv[length - 2].toNumber(state);
+        if ((length >= 1) && (argc > length - 1))
+            date = argv[length - 1].toNumber(state);
+        break;
+    case DateSetterType::Time:
+        if ((length >= 4) && (argc > length - 4))
+            hour = argv[length - 4].toNumber(state);
+        if ((length >= 3) && (argc > length - 3))
+            minute = argv[length - 3].toNumber(state);
+        if ((length >= 2) && (argc > length - 2))
+            second = argv[length - 2].toNumber(state);
+        if ((length >= 1) && (argc > length - 1))
+            millisecond = argv[length - 1].toNumber(state);
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
+        d->setTimeValueAsNaN();
+    } else if (d->isValid()) {
+        d->setTimeValue(state, year, month, date, hour, minute, second, millisecond, convertToUTC);
+    }
+
+    return Value(d->primitiveValue());
+}
+
+#define DECLARE_STATIC_DATE_SETTER(Name, setterType, length, utc)                                                                                              \
+    static Value builtinDateSet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)                           \
+    {                                                                                                                                                          \
+        return Value(builtinDateSetHelper(state, DateSetterType::setterType, length, utc, thisValue, argc, argv, state.context()->staticStrings().set##Name)); \
+    }
+
+FOR_EACH_DATE_VALUES(DECLARE_STATIC_DATE_SETTER);
+
+static Value builtinDateSetTime(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, setTime);
+    if (argc > 0) {
+        thisObject->setTimeValue(DateObject::timeClip(state, argv[0].toNumber(state)));
+        return Value(thisObject->primitiveValue());
+    } else {
+        double value = std::numeric_limits<double>::quiet_NaN();
+        thisObject->setTimeValueAsNaN();
+        return Value(value);
+    }
+}
+
+static Value builtinDateGetYear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getYear);
+    if (!(thisObject->isValid())) {
+        return Value(std::numeric_limits<double>::quiet_NaN());
+    }
+    int ret = thisObject->getFullYear(state) - 1900;
+    return Value(ret);
+}
+
+static Value builtinDateSetYear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, setYear);
+    DateObject* d = thisObject;
+
+    if (!(d->isValid())) {
+        d->setTimeValue(DateObject::timeClip(state, 0));
+        d->setTimeValue(d->getTimezoneOffset(state) * const_Date_msPerMinute);
+    }
+    ASSERT(d->isValid());
+
+    if (argc < 1) {
+        d->setTimeValueAsNaN();
+        return Value(d->primitiveValue());
+    }
+
+    double y;
+    int month, date, hour, minute, second, millisecond;
+
+    // Let y be ToNumber(year).
+    y = argv[0].toNumber(state);
+    // If y is NaN, set the [[DateValue]] internal slot of this Date object to NaN and return NaN.
+    if (std::isnan(y)) {
+        d->setTimeValueAsNaN();
+        return Value(d->primitiveValue());
+    }
+
+    month = d->getMonth(state);
+    date = d->getDate(state);
+    hour = d->getHours(state);
+    minute = d->getMinutes(state);
+    second = d->getSeconds(state);
+    millisecond = d->getMilliseconds(state);
+
+    double yyyy;
+    double yAsInteger = Value(y).toInteger(state);
+    // If y is not NaN and 0 ≤ ToInteger(y) ≤ 99, let yyyy be ToInteger(y) + 1900.
+    if (0 <= yAsInteger && yAsInteger <= 99) {
+        yyyy = 1900 + yAsInteger;
+    } else {
+        // Else, let yyyy be y.
+        yyyy = y;
+    }
+
+    if (d->isValid()) {
+        d->setTimeValue(state, yyyy, month, date, hour, minute, second, millisecond);
+    }
+
+    return Value(d->primitiveValue());
+}
+
+static Value builtinDateGetTimezoneOffset(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getTimezoneOffset);
+    if (!(thisObject->isValid()))
+        return Value(std::numeric_limits<double>::quiet_NaN());
+    return Value(thisObject->getTimezoneOffset(state));
+}
+
+static Value builtinDateToPrimitive(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the this value.
+    Value O = thisValue;
+    // If Type(O) is not Object, throw a TypeError exception.
+    if (!O.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Date.string(), true,
+                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    bool tryFirstIsString = false;
+    // If hint is the String value "string" or the String value "default", then
+    if (argv[0].isString() && (argv[0].asString()->equals("string") || argv[0].asString()->equals("default"))) {
+        // Let tryFirst be "string".
+        tryFirstIsString = true;
+    } else if (argv[0].isString() && argv[0].asString()->equals("number")) {
+        // Else if hint is the String value "number", then
+        // Let tryFirst be "number".
+        tryFirstIsString = false;
+    } else {
+        // Else, throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Date.string(), true,
+                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+    }
+    // Return ? OrdinaryToPrimitive(O, tryFirst).
+    if (tryFirstIsString) {
+        return O.ordinaryToPrimitive(state, Value::PreferString);
+    } else {
+        return O.ordinaryToPrimitive(state, Value::PreferNumber);
+    }
+}
+
+void GlobalObject::installDate(ExecutionState& state)
+{
+    m_date = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Date, builtinDateConstructor, 7), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_date->setGlobalIntrinsicObject(state);
+
+    m_datePrototype = new Object(state);
+    m_datePrototype->setGlobalIntrinsicObject(state, true);
+
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().now),
+                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().now, builtinDateNow, 0, NativeFunctionInfo::Strict)),
+                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parse),
+                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().parse, builtinDateParse, 1, NativeFunctionInfo::Strict)),
+                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().UTC),
+                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().UTC, builtinDateUTC, 7, NativeFunctionInfo::Strict)),
+                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getTime),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getTime, builtinDateGetTime, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().setTime),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setTime, builtinDateSetTime, 1, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinDateValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinDateToString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toDateString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toDateString, builtinDateToDateString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toTimeString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toTimeString, builtinDateToTimeString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinDateToLocaleString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleDateString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleDateString, builtinDateToLocaleDateString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleTimeString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleTimeString, builtinDateToLocaleTimeString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toISOString),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toISOString, builtinDateToISOString, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toJSON),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toJSON, builtinDateToJSON, 1, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    FunctionObject* toUTCString = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toUTCString, builtinDateToUTCString, 0, NativeFunctionInfo::Strict));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toUTCString),
+                                       ObjectPropertyDescriptor(toUTCString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toGMTString),
+                                       ObjectPropertyDescriptor(toUTCString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getYear),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getYear, builtinDateGetYear, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().setYear),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setYear, builtinDateSetYear, 1, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getTimezoneOffset),
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getTimezoneOffset, builtinDateGetTimezoneOffset, 0, NativeFunctionInfo::Strict)),
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_datePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toPrimitive)),
+                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.toPrimitive]")), builtinDateToPrimitive, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+#define DATE_DEFINE_GETTER(dname, unused1, unused2, unused3)                                                                                                                                                            \
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##dname),                                                                                                          \
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get##dname, builtinDateGet##dname, 0, NativeFunctionInfo::Strict)), \
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    FOR_EACH_DATE_VALUES(DATE_DEFINE_GETTER);
+    DATE_DEFINE_GETTER(Day, -, -, -);
+    DATE_DEFINE_GETTER(UTCDay, -, -, -);
+
+#define DATE_DEFINE_SETTER(dname, unused1, length, unused3)                                                                                                                                                                  \
+    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().set##dname),                                                                                                               \
+                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set##dname, builtinDateSet##dname, length, NativeFunctionInfo::Strict)), \
+                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    FOR_EACH_DATE_VALUES(DATE_DEFINE_SETTER);
+
+    m_date->setFunctionPrototype(state, m_datePrototype);
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Date),
+                      ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinError.cpp
new file mode 100644 (file)
index 0000000..e0bd9c6
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/ErrorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->errorPrototype();
+    });
+    ErrorObject* obj = new ErrorObject(state, proto, String::emptyString);
+
+    Value message = argv[0];
+    if (!message.isUndefined()) {
+        obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
+                                                            ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+    }
+    return obj;
+}
+
+#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName)                                                                                                                                                                                                              \
+    static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)                                                                                                                  \
+    {                                                                                                                                                                                                                                                                 \
+        if (!newTarget.hasValue()) {                                                                                                                                                                                                                                  \
+            newTarget = state.resolveCallee();                                                                                                                                                                                                                        \
+        }                                                                                                                                                                                                                                                             \
+        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {                                                                                                               \
+            return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype();                                                                                                                                                                            \
+        });                                                                                                                                                                                                                                                           \
+        ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString);                                                                                                                                                                             \
+        Value message = argv[0];                                                                                                                                                                                                                                      \
+        if (!message.isUndefined()) {                                                                                                                                                                                                                                 \
+            obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,                                                                                                                                                      \
+                                                                ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
+        }                                                                                                                                                                                                                                                             \
+        return obj;                                                                                                                                                                                                                                                   \
+    }
+
+DEFINE_ERROR_CTOR(Reference, reference);
+DEFINE_ERROR_CTOR(Type, type);
+DEFINE_ERROR_CTOR(Syntax, syntax);
+DEFINE_ERROR_CTOR(Range, range);
+DEFINE_ERROR_CTOR(URI, uri);
+DEFINE_ERROR_CTOR(Eval, eval);
+
+static Value builtinAggregateErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+    // Let O be ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->aggregateErrorPrototype();
+    });
+    ErrorObject* O = new AggregateErrorObject(state, proto, String::emptyString);
+    Value message = argv[1];
+    // If message is not undefined, then
+    if (!message.isUndefined()) {
+        // Let msg be ? ToString(message).
+        // Let msgDesc be the PropertyDescriptor { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
+        // Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
+        O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
+                                                          ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+    }
+
+    // Let errorsList be ? IterableToList(errors).
+    auto errorsList = IteratorObject::iterableToList(state, argv[0]);
+    // Perform ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errorsList) }).
+    O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, String::fromASCII("errors")),
+                                                      ObjectPropertyDescriptor(Value(Object::createArrayFromList(state, errorsList.size(), errorsList.data())), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+    // Return O.
+    return O;
+}
+
+static Value builtinErrorThrowTypeError(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "");
+    return Value();
+}
+
+static Value builtinErrorToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject())
+        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, state.context()->staticStrings().Error.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+
+    Object* o = thisValue.toObject(state);
+
+    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(o)) {
+        return String::emptyString;
+    }
+    ToStringRecursionPreventerItemAutoHolder holder(state, o);
+
+    Value name = o->get(state, state.context()->staticStrings().name).value(state, o);
+    String* nameStr;
+    if (name.isUndefined()) {
+        nameStr = state.context()->staticStrings().Error.string();
+    } else {
+        nameStr = name.toString(state);
+    }
+    Value message = o->get(state, state.context()->staticStrings().message).value(state, o);
+    String* messageStr;
+    if (message.isUndefined()) {
+        messageStr = String::emptyString;
+    } else {
+        messageStr = message.toString(state);
+    }
+
+    if (nameStr->length() == 0) {
+        return messageStr;
+    }
+
+    if (messageStr->length() == 0) {
+        return nameStr;
+    }
+
+    StringBuilder builder;
+    builder.appendString(nameStr);
+    builder.appendString(": ");
+    builder.appendString(messageStr);
+    return builder.finalize(&state);
+}
+
+void GlobalObject::installError(ExecutionState& state)
+{
+    m_error = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Error, builtinErrorConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_error->setGlobalIntrinsicObject(state);
+
+    m_errorPrototype = new Object(state);
+    m_errorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_error->setFunctionPrototype(state, m_errorPrototype);
+
+    m_errorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(state.context()->staticStrings().Error.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    auto errorToStringFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinErrorToString, 0, NativeFunctionInfo::Strict));
+    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().toString, ObjectPropertyDescriptor(errorToStringFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.3
+    // 13.2.3 The [[ThrowTypeError]] Function Object
+    m_throwTypeError = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinErrorThrowTypeError, 0, NativeFunctionInfo::Strict));
+    m_throwTypeError->setGlobalIntrinsicObject(state, false);
+    m_throwTypeError->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().length),
+                                        ObjectPropertyDescriptor(Value(0), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
+    m_throwTypeError->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().name),
+                                        ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
+    m_throwTypeError->preventExtensions(state);
+
+    m_throwerGetterSetterData = new JSGetterSetter(m_throwTypeError, m_throwTypeError);
+
+#define DEFINE_ERROR(errorname, bname, length)                                                                                                                                                                                                                                                                                          \
+    m_##errorname##Error = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bname##Error, builtin##bname##ErrorConstructor, length), NativeFunctionObject::__ForBuiltinConstructor__);                                                                                                               \
+    m_##errorname##Error->setPrototype(state, m_error);                                                                                                                                                                                                                                                                                 \
+    m_##errorname##ErrorPrototype = new Object(state, m_errorPrototype);                                                                                                                                                                                                                                                                \
+    m_##errorname##ErrorPrototype->setGlobalIntrinsicObject(state, true);                                                                                                                                                                                                                                                               \
+    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().constructor, ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));                            \
+    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));                                 \
+    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(state.context()->staticStrings().bname##Error.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
+    m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype);                                                                                                                                                                                                                                                   \
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error),                                                                                                                                                                                                                                         \
+                      ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+
+    DEFINE_ERROR(reference, Reference, 1);
+    DEFINE_ERROR(type, Type, 1);
+    DEFINE_ERROR(syntax, Syntax, 1);
+    DEFINE_ERROR(range, Range, 1);
+    DEFINE_ERROR(uri, URI, 1);
+    DEFINE_ERROR(eval, Eval, 1);
+    DEFINE_ERROR(aggregate, Aggregate, 2);
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Error),
+                      ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFinalizationRegistry.cpp
new file mode 100644 (file)
index 0000000..e2ca14c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/FinalizationRegistryObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+#define RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(NAME, BUILT_IN_METHOD)                                                                                                                                                                                               \
+    if (!thisValue.isObject() || !thisValue.asObject()->isFinalizationRegistryObject()) {                                                                                                                                                                                 \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().FinalizationRegistry.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                                     \
+    FinalizationRegistryObject* NAME = thisValue.asObject()->asFinalizationRegistryObject();
+
+static Value builtinFinalizationRegistryConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+    if (argc == 0 || !argv[0].isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "cleanup Callback is not callable");
+    }
+
+    // Let finalizationRegistry be ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistryPrototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->finalizationRegistryPrototype();
+    });
+
+    return new FinalizationRegistryObject(state, proto, argv[0].asObject(), state.resolveCallee()->getFunctionRealm(state));
+}
+
+static Value builtinfinalizationRegistryRegister(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, stringRegister);
+
+    if (argc == 0 || !argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target is not object");
+    }
+    if (argv[0] == argv[1]) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target and heldValue is the same");
+    }
+
+    Optional<Object*> unregisterToken;
+    if (argc >= 3) {
+        if (argv[2].isObject()) {
+            unregisterToken = argv[2].asObject();
+        } else if (!argv[2].isUndefined()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "unregisterToken is not undefined");
+        }
+    }
+    finalRegistry->setCell(state, argv[0].asObject(), argv[1], unregisterToken);
+    return Value();
+}
+
+static Value builtinfinalizationRegistryUnregister(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, unregister);
+    if (argc == 0 || !argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "unregisterToken is not object");
+    }
+    return Value(finalRegistry->deleteCell(state, argv[0].asObject()));
+}
+
+static Value builtinfinalizationRegistryCleanupSome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, cleanupSome);
+
+    // If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception
+    Object* callback = nullptr;
+    if (argc && !argv[0].isUndefined()) {
+        if (!argv[0].isCallable()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "callback is not callable");
+        }
+        callback = argv[0].asObject();
+    }
+
+    finalRegistry->cleanupSome(state, callback);
+
+    return Value();
+}
+
+void GlobalObject::installFinalizationRegistry(ExecutionState& state)
+{
+    m_finalizationRegistry = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().FinalizationRegistry, builtinFinalizationRegistryConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_finalizationRegistry->setGlobalIntrinsicObject(state);
+
+    m_finalizationRegistryPrototype = new Object(state, m_objectPrototype);
+    m_finalizationRegistryPrototype->setGlobalIntrinsicObject(state, true);
+    m_finalizationRegistryPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                                      ObjectPropertyDescriptor(Value(state.context()->staticStrings().FinalizationRegistry.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // FinalizationRegistry.prototype.unregister
+    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().unregister),
+                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().unregister, builtinfinalizationRegistryUnregister, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // FinalizationRegistry.prototype.register
+    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringRegister),
+                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringRegister, builtinfinalizationRegistryRegister, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // https://github.com/tc39/proposal-cleanup-some
+    // FinalizationRegistry.prototype.cleanupSome
+    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cleanupSome),
+                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cleanupSome, builtinfinalizationRegistryCleanupSome, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_finalizationRegistry->setFunctionPrototype(state, m_finalizationRegistryPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().FinalizationRegistry),
+                      ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::NonEnumerablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinFunction.cpp
new file mode 100644 (file)
index 0000000..197cb7f
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/BoundFunctionObject.h"
+#include "runtime/ScriptFunctionObject.h"
+#include "runtime/ScriptClassConstructorFunctionObject.h"
+#include "parser/Lexer.h"
+
+namespace Escargot {
+
+static Value builtinFunctionEmptyFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return Value();
+}
+
+static Value builtinFunctionConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (newTarget.hasValue() && UNLIKELY((bool)state.context()->securityPolicyCheckCallback())) {
+        Value checkMSG = state.context()->securityPolicyCheckCallback()(state, false);
+        if (!checkMSG.isEmpty()) {
+            ASSERT(checkMSG.isString());
+            ErrorObject::throwBuiltinError(state, ErrorObject::Code::EvalError, checkMSG.asString());
+            return Value();
+        }
+    }
+
+    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
+    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
+    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, false, false, false);
+
+    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->functionPrototype();
+    });
+
+    ScriptFunctionObject* result = new ScriptFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment, true, false, false);
+
+    return result;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-function.prototype.tostring
+static Value builtinFunctionToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (LIKELY(thisValue.isObject())) {
+        Object* func = thisValue.asObject();
+
+        if (LIKELY(func->isFunctionObject())) {
+            FunctionObject* fn = func->asFunctionObject();
+
+            if (fn->isScriptClassConstructorFunctionObject()) {
+                return fn->asScriptFunctionObject()->asScriptClassConstructorFunctionObject()->classSourceCode();
+            } else {
+                StringBuilder builder;
+                if (fn->isScriptFunctionObject()) {
+                    StringView src = fn->asScriptFunctionObject()->interpretedCodeBlock()->src();
+                    size_t length = src.length();
+                    while (length > 0 && EscargotLexer::isWhiteSpaceOrLineTerminator(src[length - 1])) {
+                        length--;
+                    }
+                    builder.appendString(new StringView(src, 0, length));
+                } else {
+                    ASSERT(fn->isNativeFunctionObject());
+                    builder.appendString("function ");
+                    builder.appendString(fn->codeBlock()->functionName().string());
+                    builder.appendString("() { [native code] }");
+                }
+
+                return builder.finalize(&state);
+            }
+        }
+
+        if (func->isBoundFunctionObject() || func->isCallable()) {
+            StringBuilder builder;
+            builder.appendString("function () { [native code] }");
+            return builder.finalize(&state);
+        }
+    }
+
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
+    return Value();
+}
+
+static Value builtinFunctionApply(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
+    }
+    Value thisArg = argv[0];
+    Value argArray = argv[1];
+    size_t arrlen = 0;
+    Value* arguments = nullptr;
+    ValueVector argList;
+    if (argArray.isUndefinedOrNull()) {
+        // TODO
+    } else {
+        argList = Object::createListFromArrayLike(state, argArray);
+        arrlen = argList.size();
+        arguments = argList.data();
+    }
+
+    return Object::call(state, thisValue, thisArg, arrlen, arguments);
+}
+
+static Value builtinFunctionCall(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
+    }
+    Value thisArg = argv[0];
+    size_t arrlen = argc > 0 ? argc - 1 : 0;
+    Value* arguments = ALLOCA(sizeof(Value) * arrlen, Value, state);
+    for (size_t i = 0; i < arrlen; i++) {
+        arguments[i] = argv[i + 1];
+    }
+
+    return Object::call(state, thisValue, thisArg, arrlen, arguments);
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.bind
+static Value builtinFunctionBind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If IsCallable(Target) is false, throw a TypeError exception.
+    if (!thisValue.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().bind.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
+    }
+
+    // Let Target be the this value.
+    Object* target = thisValue.asObject();
+
+    // Let args be a new (possibly empty) List consisting of all of the argument values provided after thisArg in order.
+    Value boundThis = argv[0];
+    size_t boundArgc = (argc > 0) ? argc - 1 : 0;
+    Value* boundArgv = (boundArgc > 0) ? argv + 1 : nullptr;
+    //BoundFunctionObject* F = new BoundFunctionObject(state, thisValue, boundThis, boundArgc, boundArgv);
+
+    // Let targetHasLength be HasOwnProperty(Target, "length").
+    bool targetHasLength = target->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().length));
+    double length = 0;
+    // If targetHasLength is true, then
+    if (targetHasLength) {
+        // Let targetLen be Get(Target, "length").
+        Value targetLen = target->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, target);
+        // If Type(targetLen) is not Number, let L be 0.
+        // Else Let targetLen be ToInteger(targetLen).
+        // Let L be the larger of 0 and the result of targetLen minus the number of elements of args.
+        if (targetLen.isNumber()) {
+            length = std::max(0.0, targetLen.toInteger(state) - boundArgc);
+        }
+    }
+
+    // F->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length),
+    //                                    ObjectPropertyDescriptor(Value(length), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // Let targetName be Get(Target, "name").
+    Value targetName = target->get(state, ObjectPropertyName(state.context()->staticStrings().name)).value(state, target);
+    // If Type(targetName) is not String, let targetName be the empty string.
+    if (!targetName.isString()) {
+        targetName = String::emptyString;
+    }
+
+    StringBuilder builder;
+    builder.appendString("bound ");
+    builder.appendString(targetName.asString());
+    //F->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().name),
+    //                                    ObjectPropertyDescriptor(Value(builder.finalize(&state)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // Let F be BoundFunctionCreate(Target, thisArg, args).
+    // Let status be DefinePropertyOrThrow(F, "length", PropertyDescriptor {[[Value]]: L, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
+    // Perform SetFunctionName(F, targetName, "bound").
+    // Return F.
+    return new BoundFunctionObject(state, target, boundThis, boundArgc, boundArgv, Value(length), Value(builder.finalize(&state)));
+}
+
+static Value builtinFunctionHasInstanceOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        return Value(false);
+    }
+    return Value(thisValue.asObject()->hasInstance(state, argv[0]));
+}
+
+void GlobalObject::installFunction(ExecutionState& state)
+{
+    m_functionPrototype = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinFunctionEmptyFunction, 0, NativeFunctionInfo::Strict),
+                                                   NativeFunctionObject::__ForGlobalBuiltin__);
+    m_functionPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_function = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Function, builtinFunctionConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_function->setGlobalIntrinsicObject(state);
+    m_function->setFunctionPrototype(state, m_functionPrototype);
+
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().constructor),
+                                                          ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toString),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinFunctionToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_functionApply = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().apply, builtinFunctionApply, 2, NativeFunctionInfo::Strict));
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().apply),
+                                                          ObjectPropertyDescriptor(m_functionApply, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().call),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().call, builtinFunctionCall, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().bind),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bind, builtinFunctionBind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().hasInstance)),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.hasInstance]")), builtinFunctionHasInstanceOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Function),
+                      ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinGeneratorFunction.cpp
new file mode 100644 (file)
index 0000000..3014125
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/GeneratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ScriptGeneratorFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinGeneratorFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
+    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
+    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, true, false, false);
+
+    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
+    if (!newTarget.hasValue()) {
+        newTarget = state.resolveCallee();
+    }
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->generator();
+    });
+
+    return new ScriptGeneratorFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
+}
+
+static Value builtinGeneratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return GeneratorObject::generatorResume(state, thisValue, argc > 0 ? argv[0] : Value());
+}
+
+static Value builtinGeneratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return GeneratorObject::generatorResumeAbrupt(state, thisValue, argc > 0 ? argv[0] : Value(), GeneratorObject::GeneratorAbruptType::Return);
+}
+
+static Value builtinGeneratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return GeneratorObject::generatorResumeAbrupt(state, thisValue, argc > 0 ? argv[0] : Value(), GeneratorObject::GeneratorAbruptType::Throw);
+}
+
+void GlobalObject::installGenerator(ExecutionState& state)
+{
+    // %GeneratorFunction% : The constructor of generator objects
+    m_generatorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().GeneratorFunction, builtinGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_generatorFunction->setGlobalIntrinsicObject(state);
+
+    // %Generator% : The initial value of the prototype property of %GeneratorFunction%
+    m_generator = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().GeneratorFunction, nullptr, 0, NativeFunctionInfo::Strict));
+    m_generator->setGlobalIntrinsicObject(state, true);
+    m_generatorFunction->setFunctionPrototype(state, m_generator);
+
+
+    // 25.2.3.1 The initial value of GeneratorFunction.prototype.constructor is the intrinsic object %GeneratorFunction%.
+    m_generator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_generatorFunction, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // %GeneratorPrototype% : The initial value of the prototype property of %Generator%
+    m_generatorPrototype = new Object(state, m_iteratorPrototype);
+    m_generatorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_generator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().prototype), ObjectPropertyDescriptor(m_generatorPrototype, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    // 25.2.3.3 GeneratorFunction.prototype [ @@toStringTag ]
+    // The initial value of the @@toStringTag property is the String value "GeneratorFunction"..
+    // This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
+    m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                  ObjectPropertyDescriptor(Value(state.context()->staticStrings().GeneratorFunction.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // The initial value of Generator.prototype.constructor is the intrinsic object %Generator%.
+    m_generatorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_generator, ObjectPropertyDescriptor::ConfigurablePresent));
+
+    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinGeneratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
+                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinGeneratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
+                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinGeneratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-generatorfunction.prototype-@@tostringtag
+    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                           ObjectPropertyDescriptor(Value(state.context()->staticStrings().Generator.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIntl.cpp
new file mode 100644 (file)
index 0000000..cfa9c67
--- /dev/null
@@ -0,0 +1,1148 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
+ * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2017-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/StringObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/DateObject.h"
+#include "runtime/BigInt.h"
+#include "intl/Intl.h"
+#include "intl/IntlCollator.h"
+#include "intl/IntlNumberFormat.h"
+#include "intl/IntlDateTimeFormat.h"
+#include "intl/IntlPluralRules.h"
+#include "intl/IntlLocale.h"
+#include "intl/IntlRelativeTimeFormat.h"
+
+namespace Escargot {
+
+static Value builtinIntlCollatorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl.collator
+    Value locales, options;
+    if (argc >= 1) {
+        locales = argv[0];
+    }
+    if (argc >= 2) {
+        options = argv[1];
+    }
+
+    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
+    if (!newTarget) {
+        newTarget = state.resolveCallee();
+    }
+
+    // Let internalSlotsList be « [[InitializedCollator]], [[Locale]], [[Usage]], [[Sensitivity]], [[IgnorePunctuation]], [[Collation]], [[BoundCompare]] ».
+    // If %Collator%.[[RelevantExtensionKeys]] contains "kn", then
+    // Append [[Numeric]] as the last element of internalSlotsList.
+    // If %Collator%.[[RelevantExtensionKeys]] contains "kf", then
+    // Append [[CaseFirst]] as the last element of internalSlotsList.
+    // Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%CollatorPrototype%", internalSlotsList).
+    // Return ? InitializeCollator(collator, locales, options).
+    return IntlCollator::create(state, newTarget->getFunctionRealm(state), locales, options);
+}
+
+static Value builtinIntlCollatorCompare(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    FunctionObject* callee = state.resolveCallee();
+    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* colllator = callee->asObject();
+
+    String* x = argv[0].toString(state);
+    String* y = argv[1].toString(state);
+
+    return Value(IntlCollator::compare(state, colllator, x, y));
+}
+
+static Value builtinIntlCollatorCompareGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+    FunctionObject* fn;
+    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyCompareFunction()));
+    if (g.hasValue()) {
+        fn = g.value(state, internalSlot).asFunction();
+    } else {
+        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlCollatorCompare, 2, NativeFunctionInfo::Strict));
+        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCompareFunction()), Value(fn), internalSlot);
+        fn->setInternalSlot(internalSlot);
+    }
+
+    return fn;
+}
+
+static Value builtinIntlCollatorResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+    auto r = IntlCollator::resolvedOptions(state, internalSlot);
+    Object* result = new Object(state);
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(r.locale, ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage()), ObjectPropertyDescriptor(r.usage, ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), ObjectPropertyDescriptor(r.sensitivity, ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation()), ObjectPropertyDescriptor(Value(r.ignorePunctuation), ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().collation), ObjectPropertyDescriptor(r.collation, ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().numeric), ObjectPropertyDescriptor(Value(r.numeric), ObjectPropertyDescriptor::AllPresent));
+    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().caseFirst), ObjectPropertyDescriptor(Value(r.caseFirst), ObjectPropertyDescriptor::AllPresent));
+    return result;
+}
+
+static Value builtinIntlCollatorSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If options is not provided, then let options be undefined.
+    Value locales = argv[0];
+    Value options;
+    if (argc >= 2) {
+        options = argv[1];
+    }
+    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.Collator.
+    const auto& availableLocales = state.context()->vmInstance()->intlCollatorAvailableLocales();
+    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
+    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
+}
+
+
+static Value builtinIntlDateTimeFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value locales, options;
+    if (argc >= 1) {
+        locales = argv[0];
+    }
+    if (argc >= 2) {
+        options = argv[1];
+    }
+
+    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
+    Object* newTargetVariable;
+    if (!newTarget.hasValue()) {
+        newTargetVariable = state.resolveCallee();
+    } else {
+        newTargetVariable = newTarget.value();
+    }
+
+    // Let dateTimeFormat be ? OrdinaryCreateFromConstructor(newTarget, "%DateTimeFormatPrototype%", « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[Hour]], [[Minute]], [[Second]], [[TimeZoneName]], [[HourCycle]], [[Pattern]], [[BoundFormat]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTargetVariable, [](ExecutionState& state, Context* realm) -> Object* {
+        return realm->globalObject()->intlDateTimeFormatPrototype();
+    });
+    Object* dateTimeFormat = new Object(state, proto);
+    IntlDateTimeFormat::initialize(state, dateTimeFormat, locales, options);
+    return dateTimeFormat;
+}
+
+static Value builtinIntlDateTimeFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    FunctionObject* callee = state.resolveCallee();
+    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* dateTimeFormat = callee->asObject();
+    double value;
+    if (argc == 0 || argv[0].isUndefined()) {
+        value = DateObject::currentTime();
+    } else {
+        value = argv[0].toNumber(state);
+    }
+    auto result = IntlDateTimeFormat::format(state, dateTimeFormat, value);
+
+    return Value(new UTF16String(result.data(), result.length()));
+}
+
+static Value builtinIntlDateTimeFormatFormatGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+    FunctionObject* fn;
+    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().format));
+    if (g.hasValue()) {
+        fn = g.value(state, internalSlot).asFunction();
+    } else {
+        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlDateTimeFormatFormat, 1, NativeFunctionInfo::Strict));
+        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().format), Value(fn), internalSlot);
+        fn->setInternalSlot(internalSlot);
+    }
+
+    return fn;
+}
+
+static Value builtinIntlDateTimeFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let dtf be this value.
+    // If Type(dtf) is not Object, throw a TypeError exception.
+    // If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception.
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+    Value date = argv[0];
+    double x;
+    // If date is undefined, then
+    if (date.isUndefined()) {
+        // Let x be Call(%Date_now%, undefined).
+        x = DateObject::currentTime();
+    } else {
+        // Else,
+        // Let x be ? ToNumber(date).
+        x = date.toNumber(state);
+    }
+    // Return ? FormatDateTimeToParts(dtf, x).
+    return IntlDateTimeFormat::formatToParts(state, thisValue.asObject(), x);
+}
+
+static void setFormatOpt(ExecutionState& state, Object* internalSlot, Object* result, const char* pName)
+{
+    String* prop = String::fromASCII(pName);
+
+    ObjectGetResult r;
+    r = internalSlot->get(state, ObjectPropertyName(state, prop));
+
+    if (r.hasValue()) {
+        result->defineOwnProperty(state, ObjectPropertyName(state, prop), ObjectPropertyDescriptor(Value(r.value(state, internalSlot)), ObjectPropertyDescriptor::AllPresent));
+    }
+}
+
+static Value builtinIntlDateTimeFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+
+    Object* result = new Object(state);
+
+    setFormatOpt(state, internalSlot, result, "locale");
+    setFormatOpt(state, internalSlot, result, "calendar");
+    setFormatOpt(state, internalSlot, result, "numberingSystem");
+    setFormatOpt(state, internalSlot, result, "timeZone");
+    setFormatOpt(state, internalSlot, result, "hourCycle");
+    setFormatOpt(state, internalSlot, result, "hour12");
+    setFormatOpt(state, internalSlot, result, "weekday");
+    setFormatOpt(state, internalSlot, result, "era");
+    setFormatOpt(state, internalSlot, result, "year");
+    setFormatOpt(state, internalSlot, result, "month");
+    setFormatOpt(state, internalSlot, result, "day");
+    setFormatOpt(state, internalSlot, result, "hour");
+    setFormatOpt(state, internalSlot, result, "minute");
+    setFormatOpt(state, internalSlot, result, "second");
+    setFormatOpt(state, internalSlot, result, "timeZoneName");
+
+    return Value(result);
+}
+
+static Value builtinIntlDateTimeFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If options is not provided, then let options be undefined.
+    Value locales = argv[0];
+    Value options;
+    if (argc >= 2) {
+        options = argv[1];
+    }
+    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.DateTimeFormat.
+    const auto& availableLocales = state.context()->vmInstance()->intlDateTimeFormatAvailableLocales();
+    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
+    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
+}
+
+static Value builtinIntlNumberFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    FunctionObject* callee = state.resolveCallee();
+    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* numberFormat = callee->asObject();
+
+    UTF16StringDataNonGCStd result;
+    auto numeric = argv[0].toNumeric(state);
+    if (numeric.second) {
+        result = IntlNumberFormat::format(state, numberFormat, numeric.first.asBigInt()->toString());
+    } else {
+        result = IntlNumberFormat::format(state, numberFormat, numeric.first.asNumber());
+    }
+
+    return new UTF16String(result.data(), result.length());
+}
+
+static Value builtinIntlNumberFormatFormatGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+    FunctionObject* fn;
+    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().format));
+    if (g.hasValue()) {
+        fn = g.value(state, internalSlot).asFunction();
+    } else {
+        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlNumberFormatFormat, 1, NativeFunctionInfo::Strict));
+        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().format), Value(fn), internalSlot);
+        fn->setInternalSlot(internalSlot);
+    }
+
+    return fn;
+}
+
+static Value builtinIntlNumberFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value locales, options;
+    if (argc >= 1) {
+        locales = argv[0];
+    }
+    if (argc >= 2) {
+        options = argv[1];
+    }
+
+    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
+    Object* newTargetVariable;
+    if (!newTarget.hasValue()) {
+        newTargetVariable = state.resolveCallee();
+    } else {
+        newTargetVariable = newTarget.value();
+    }
+
+    // Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormatPrototype%", « [[InitializedNumberFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[Unit]], [[UnitDisplay]], [[Currency]], [[CurrencyDisplay]], [[CurrencySign]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]], [[Notation]], [[CompactDisplay]], [[UseGrouping]], [[SignDisplay]], [[BoundFormat]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTargetVariable, [](ExecutionState& state, Context* realm) -> Object* {
+        return realm->globalObject()->intlNumberFormatPrototype();
+    });
+    Object* numberFormat = new Object(state, proto);
+    IntlNumberFormat::initialize(state, numberFormat, locales, options);
+    return numberFormat;
+}
+
+static Value builtinIntlNumberFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, state.context()->staticStrings().lazyInitializedNumberFormat())) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    Object* internalSlot = thisValue.asObject()->internalSlot();
+    Object* result = new Object(state);
+
+    setFormatOpt(state, internalSlot, result, "locale");
+    setFormatOpt(state, internalSlot, result, "numberingSystem");
+    setFormatOpt(state, internalSlot, result, "style");
+    setFormatOpt(state, internalSlot, result, "currency");
+    setFormatOpt(state, internalSlot, result, "currencyDisplay");
+    setFormatOpt(state, internalSlot, result, "currencySign");
+    setFormatOpt(state, internalSlot, result, "unit");
+    setFormatOpt(state, internalSlot, result, "unitDisplay");
+    setFormatOpt(state, internalSlot, result, "minimumIntegerDigits");
+    setFormatOpt(state, internalSlot, result, "minimumFractionDigits");
+    setFormatOpt(state, internalSlot, result, "maximumFractionDigits");
+    setFormatOpt(state, internalSlot, result, "minimumSignificantDigits");
+    setFormatOpt(state, internalSlot, result, "maximumSignificantDigits");
+    setFormatOpt(state, internalSlot, result, "useGrouping");
+    setFormatOpt(state, internalSlot, result, "notation");
+    setFormatOpt(state, internalSlot, result, "compactDisplay");
+    setFormatOpt(state, internalSlot, result, "signDisplay");
+    return result;
+}
+
+static Value builtinIntlNumberFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let nf be the this value.
+    // If Type(nf) is not Object, throw a TypeError exception.
+    // If nf does not have an [[InitializedNumberFormat]] internal slot, throw a TypeError exception.
+    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, state.context()->staticStrings().lazyInitializedNumberFormat())) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+    // Let x be ? ToNumeric(value).
+    double x = argv[0].toNumber(state);
+    // Return ? FormatNumericToParts(nf, x).
+    return IntlNumberFormat::formatToParts(state, thisValue.asObject(), x);
+}
+
+static Value builtinIntlNumberFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If options is not provided, then let options be undefined.
+    Value locales = argv[0];
+    Value options;
+    if (argc >= 2) {
+        options = argv[1];
+    }
+    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.NumberFormat.
+    const auto& availableLocales = state.context()->vmInstance()->intlNumberFormatAvailableLocales();
+    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
+    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
+}
+
+static Value builtinIntlPluralRulesConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, throw a TypeError exception.
+    if (!newTarget) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+#if defined(ENABLE_RUNTIME_ICU_BINDER)
+    UVersionInfo versionArray;
+    u_getVersion(versionArray);
+    if (versionArray[0] < 60) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.PluralRules needs 60+ version of ICU");
+    }
+#endif
+
+    Value locales = argc >= 1 ? argv[0] : Value();
+    Value options = argc >= 2 ? argv[1] : Value();
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->intlPluralRulesPrototype();
+    });
+
+    return new IntlPluralRulesObject(state, proto, locales, options);
+}
+
+static Value builtinIntlPluralRulesSelect(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl.pluralrules.prototype.select
+    // Let pr be the this value.
+    // If Type(pr) is not Object, throw a TypeError exception.
+    // If pr does not have an [[InitializedPluralRules]] internal slot, throw a TypeError exception.
+    if (!thisValue.isObject() || !thisValue.asObject()->isIntlPluralRulesObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+    // Let n be ? ToNumber(value).
+    double n = argv[0].toNumber(state);
+    // Return ? ResolvePlural(pr, n).
+    return thisValue.asObject()->asIntlPluralRulesObject()->asIntlPluralRulesObject()->resolvePlural(n);
+}
+
+static Value builtinIntlPluralRulesResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let pr be the this value.
+    // If Type(pr) is not Object, throw a TypeError exception.
+    // If pr does not have an [[InitializedPluralRules]] internal slot, throw a TypeError exception.
+    if (!thisValue.isObject() || !thisValue.asObject()->isIntlPluralRulesObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    IntlPluralRulesObject* pr = thisValue.asObject()->asIntlPluralRulesObject();
+
+    // Let options be ! ObjectCreate(%ObjectPrototype%).
+    Object* options = new Object(state);
+    // For each row of Table 8, except the header row, in table order, do
+    // Let p be the Property value of the current row.
+    // Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row.
+    // If v is not undefined, then
+    // Perform ! CreateDataPropertyOrThrow(options, p, v).
+
+
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(pr->locale(), ObjectPropertyDescriptor::AllPresent));
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyType()), ObjectPropertyDescriptor(pr->type(), ObjectPropertyDescriptor::AllPresent));
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits()), ObjectPropertyDescriptor(Value(pr->minimumIntegerDigits()), ObjectPropertyDescriptor::AllPresent));
+
+    if (pr->minimumSignificantDigits()) {
+        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()), ObjectPropertyDescriptor(Value(pr->minimumSignificantDigits().value()), ObjectPropertyDescriptor::AllPresent));
+        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()), ObjectPropertyDescriptor(Value(pr->maximumSignificantDigits().value()), ObjectPropertyDescriptor::AllPresent));
+    } else {
+        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), ObjectPropertyDescriptor(Value(pr->minimumFractionDigits()), ObjectPropertyDescriptor::AllPresent));
+        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), ObjectPropertyDescriptor(Value(pr->maximumFractionDigits()), ObjectPropertyDescriptor::AllPresent));
+    }
+
+
+    // Let pluralCategories be a List of Strings representing the possible results of PluralRuleSelect for the selected locale pr.[[Locale]]. This List consists of unique string values, from the the list "zero", "one", "two", "few", "many" and "other", that are relevant for the locale whose localization is specified in LDML Language Plural Rules.
+    // Perform ! CreateDataProperty(options, "pluralCategories", CreateArrayFromList(pluralCategories)).
+    ArrayObject* pluralCategories = new ArrayObject(state);
+
+    UErrorCode status = U_ZERO_ERROR;
+    UEnumeration* ue = uplrules_getKeywords(pr->icuPluralRules(), &status);
+    ASSERT(U_SUCCESS(status));
+    uint32_t i = 0;
+
+    do {
+        int32_t size;
+        const char* str = uenum_next(ue, &size, &status);
+        ASSERT(U_SUCCESS(status));
+
+        if (!str) {
+            break;
+        }
+
+        String* s = String::fromUTF8(str, size);
+        pluralCategories->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, (size_t)i), ObjectPropertyDescriptor(Value(s), ObjectPropertyDescriptor::AllPresent));
+        i++;
+    } while (true);
+
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(AtomicString(state.context()->atomicStringMap(), "pluralCategories", sizeof("pluralCategories") - 1, AtomicString::FromExternalMemory)),
+                                              ObjectPropertyDescriptor(pluralCategories, ObjectPropertyDescriptor::AllPresent));
+
+    uenum_close(ue);
+    // Return options.
+    return options;
+}
+
+static Value builtinIntlPluralRulesSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If options is not provided, then let options be undefined.
+    Value locales = argv[0];
+    Value options;
+    if (argc >= 2) {
+        options = argv[1];
+    }
+    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.Collator.
+    const auto& availableLocales = state.context()->vmInstance()->intlPluralRulesAvailableLocales();
+    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
+    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
+}
+
+static Value builtinIntlLocaleConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, throw a TypeError exception.
+    if (!newTarget) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    Value tagValue = argv[0];
+
+    // If Type(tag) is not String or Object, throw a TypeError exception.
+    if (!tagValue.isObject() && !tagValue.isString()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "First argument of Intl.Locale should be String or Object");
+    }
+
+    String* tag;
+    // If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then
+    if (tagValue.isObject() && tagValue.asObject()->isIntlLocaleObject()) {
+        // Let tag be tag.[[Locale]].
+        tag = tagValue.asObject()->asIntlLocaleObject()->locale();
+    } else {
+        // Else,
+        // Let tag be ? ToString(tag).
+        tag = tagValue.toString(state);
+    }
+
+    Optional<Object*> options;
+    // If options is undefined, then
+    if (argc <= 1 || argv[1].isUndefined()) {
+        // Let options be ! ObjectCreate(null).
+    } else {
+        // Let options be ? ToObject(options).
+        options = argv[1].toObject(state);
+    }
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->intlLocalePrototype();
+    });
+    return new IntlLocaleObject(state, proto, tag, options);
+}
+
+static Value builtinIntlLocaleToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let loc be the this value.
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+    // Return loc.[[Locale]].
+    return loc.asObject()->asIntlLocaleObject()->locale();
+}
+
+static Value builtinIntlLocaleBaseNameGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->baseName();
+}
+
+static Value builtinIntlLocaleCalendarGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->calendar().hasValue() ? loc.asObject()->asIntlLocaleObject()->calendar().value() : Value();
+}
+
+static Value builtinIntlLocaleCaseFirstGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->caseFirst().hasValue() ? loc.asObject()->asIntlLocaleObject()->caseFirst().value() : Value();
+}
+
+static Value builtinIntlLocaleCollationGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->collation().hasValue() ? loc.asObject()->asIntlLocaleObject()->collation().value() : Value();
+}
+
+static Value builtinIntlLocaleHourCycleGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->hourCycle().hasValue() ? loc.asObject()->asIntlLocaleObject()->hourCycle().value() : Value();
+}
+
+static Value builtinIntlLocaleNumericGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->numeric().hasValue() ? Value(loc.asObject()->asIntlLocaleObject()->numeric().value()->equals("true")) : Value(false);
+}
+
+static Value builtinIntlLocaleNumberingSystemGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->numberingSystem().hasValue() ? loc.asObject()->asIntlLocaleObject()->numberingSystem().value() : Value();
+}
+
+static Value builtinIntlLocaleLanguageGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->language();
+}
+
+static Value builtinIntlLocaleScriptGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->script();
+}
+
+static Value builtinIntlLocaleRegionGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    return loc.asObject()->asIntlLocaleObject()->region();
+}
+
+static void icuLocleToBCP47Locale(char* buf, size_t len)
+{
+    for (size_t i = 0; i < len; i++) {
+        if (buf[i] == '_') {
+            buf[i] = '-';
+        } else if ((std::numeric_limits<char>::is_signed && buf[i] < 0) || (!std::numeric_limits<char>::is_signed && buf[i] > 127)) {
+            // when using uloc_addLikelySubtags with `und-...` input, old version of ICU shows weird behavior
+            // it contains minus value in string
+            buf[i] = 0;
+            len = i;
+            break;
+        } else if (buf[i] == '@') { // we should ignore tags after '@'. ex) es-Latn-ES@currency=ESP -> es-Latn-ES
+            buf[i] = 0;
+            len = i;
+            break;
+        }
+    }
+
+    for (size_t i = 0; i < len - 1; i++) {
+        if (buf[i] == '-' && buf[i + 1] == '-') {
+            for (size_t j = i; j < len - 1; j++) {
+                buf[j] = buf[j + 1];
+            }
+            len--;
+            buf[len] = 0;
+        }
+    }
+}
+
+static Value builtinIntlLocaleMaximize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    // Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set maximal to loc.[[Locale]].
+    // Return ! Construct(%Locale%, maximal).
+    IntlLocaleObject* localeObject = loc.asObject()->asIntlLocaleObject();
+    String* locale = localeObject->locale();
+    auto u8Locale = locale->toNonGCUTF8StringData();
+    UErrorCode status = U_ZERO_ERROR;
+    char buf[128];
+    int32_t len = uloc_addLikelySubtags(u8Locale.data(), buf, sizeof(buf), &status);
+    if (U_SUCCESS(status)) {
+        icuLocleToBCP47Locale(buf, strlen(buf));
+        StringBuilder sb;
+        sb.appendString(buf);
+        sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
+        return new IntlLocaleObject(state, sb.finalize(), nullptr);
+
+    } else if (status != U_BUFFER_OVERFLOW_ERROR) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Unexpected error is occured while parsing locale");
+    }
+    status = U_ZERO_ERROR;
+    char* newBuf = (char*)alloca(len + 1);
+    uloc_addLikelySubtags(u8Locale.data(), newBuf, len + 1, &status);
+    ASSERT(U_SUCCESS(status));
+
+    icuLocleToBCP47Locale(newBuf, strlen(newBuf));
+    StringBuilder sb;
+    sb.appendString(newBuf);
+    sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
+    return new IntlLocaleObject(state, sb.finalize(), nullptr);
+}
+
+static Value builtinIntlLocaleMinimize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value loc = thisValue;
+    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
+    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
+        // Throw a TypeError exception.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    // Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set minimal to loc.[[Locale]].
+    // Return ! Construct(%Locale%, minimal).
+    IntlLocaleObject* localeObject = loc.asObject()->asIntlLocaleObject();
+    String* locale = localeObject->locale();
+    auto u8Locale = locale->toNonGCUTF8StringData();
+    UErrorCode status = U_ZERO_ERROR;
+    char buf[128];
+    int32_t len = uloc_minimizeSubtags(u8Locale.data(), buf, sizeof(buf), &status);
+    if (U_SUCCESS(status)) {
+        icuLocleToBCP47Locale(buf, len);
+        StringBuilder sb;
+        sb.appendString(buf);
+        sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
+        return new IntlLocaleObject(state, sb.finalize(), nullptr);
+    } else if (status != U_BUFFER_OVERFLOW_ERROR) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Unexpected error is occured while parsing locale");
+    }
+    status = U_ZERO_ERROR;
+    char* newBuf = (char*)alloca(len + 1);
+    len = uloc_minimizeSubtags(u8Locale.data(), newBuf, len + 1, &status);
+    ASSERT(U_SUCCESS(status));
+
+    icuLocleToBCP47Locale(newBuf, len);
+    StringBuilder sb;
+    sb.appendString(newBuf);
+    sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
+    return new IntlLocaleObject(state, sb.finalize(), nullptr);
+}
+
+static Value builtinIntlRelativeTimeFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, throw a TypeError exception.
+    if (!newTarget) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+#if defined(ENABLE_RUNTIME_ICU_BINDER)
+    UVersionInfo versionArray;
+    u_getVersion(versionArray);
+    if (versionArray[0] < 64) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.RelativeTimeFormat needs 64+ version of ICU");
+    }
+#endif
+
+    Value locales = argc >= 1 ? argv[0] : Value();
+    Value options = argc >= 2 ? argv[1] : Value();
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->intlRelativeTimeFormatPrototype();
+    });
+
+    return new IntlRelativeTimeFormatObject(state, proto, locales, options);
+}
+
+static Value builtinIntlRelativeTimeFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    IntlRelativeTimeFormatObject* r = thisValue.asObject()->asIntlRelativeTimeFormatObject();
+
+    // Let options be ! ObjectCreate(%ObjectPrototype%).
+    Object* options = new Object(state);
+
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(r->locale(), ObjectPropertyDescriptor::AllPresent));
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyStyle()), ObjectPropertyDescriptor(r->style(), ObjectPropertyDescriptor::AllPresent));
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().numeric), ObjectPropertyDescriptor(r->numeric(), ObjectPropertyDescriptor::AllPresent));
+    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), ObjectPropertyDescriptor(r->numberingSystem(), ObjectPropertyDescriptor::AllPresent));
+
+    return options;
+}
+
+static Value builtinIntlRelativeTimeFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value locales = argv[0];
+    Value options;
+    if (argc >= 2) {
+        options = argv[1];
+    }
+    // Let availableLocales be %RelativeTimeFormat%.[[AvailableLocales]].
+    const auto& availableLocales = state.context()->vmInstance()->intlRelativeTimeFormatAvailableLocales();
+    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // Return ? SupportedLocales(availableLocales, requestedLocales, options).
+    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
+}
+
+static Value builtinIntlRelativeTimeFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    // Let relativeTimeFormat be the this value.
+    // Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
+    // Let value be ? ToNumber(value).
+    double value = argv[0].toNumber(state);
+    // Let unit be ? ToString(unit).
+    String* unit = argv[1].toString(state);
+    // Return ? FormatRelativeTime(relativeTimeFormat, value, unit).
+    return thisValue.asObject()->asIntlRelativeTimeFormatObject()->format(state, value, unit);
+}
+
+static Value builtinIntlRelativeTimeFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
+    }
+
+    // Let relativeTimeFormat be the this value.
+    // Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
+    // Let value be ? ToNumber(value).
+    double value = argv[0].toNumber(state);
+    // Let unit be ? ToString(unit).
+    String* unit = argv[1].toString(state);
+    // Return ? FormatRelativeTimeToParts(relativeTimeFormat, value, unit).
+    return thisValue.asObject()->asIntlRelativeTimeFormatObject()->formatToParts(state, value, unit);
+}
+
+static Value builtinIntlGetCanonicalLocales(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let ll be ? CanonicalizeLocaleList(locales).
+    ValueVector ll = Intl::canonicalizeLocaleList(state, argv[0]);
+    // Return CreateArrayFromList(ll);
+    return Object::createArrayFromList(state, ll);
+}
+
+void GlobalObject::installIntl(ExecutionState& state)
+{
+    m_intl = new Object(state);
+    m_intl->setGlobalIntrinsicObject(state);
+
+    const StaticStrings* strings = &state.context()->staticStrings();
+    defineOwnProperty(state, ObjectPropertyName(strings->Intl),
+                      ObjectPropertyDescriptor(m_intl, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlCollator = new NativeFunctionObject(state, NativeFunctionInfo(strings->Collator, builtinIntlCollatorConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlCollator->setGlobalIntrinsicObject(state);
+    m_intlCollator->getFunctionPrototype(state).asObject()->setGlobalIntrinsicObject(state);
+
+    FunctionObject* compareFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getCompare, builtinIntlCollatorCompareGetter, 0, NativeFunctionInfo::Strict));
+    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, state.context()->staticStrings().compare,
+                                                                              ObjectPropertyDescriptor(JSGetterSetter(compareFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
+                                                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlCollatorResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                              ObjectPropertyDescriptor(strings->intlDotCollator.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlCollator->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
+                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlCollatorSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlDateTimeFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->DateTimeFormat, builtinIntlDateTimeFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlDateTimeFormat->setGlobalIntrinsicObject(state);
+    m_intlDateTimeFormatPrototype = m_intlDateTimeFormat->getFunctionPrototype(state).asObject();
+    m_intlDateTimeFormatPrototype->setGlobalIntrinsicObject(state, true);
+
+    FunctionObject* formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlDateTimeFormatFormatGetter, 0, NativeFunctionInfo::Strict));
+    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
+                                                     ObjectPropertyDescriptor(JSGetterSetter(formatFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlDateTimeFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlDateTimeFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlDateTimeFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
+                                            ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlDateTimeFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlNumberFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->NumberFormat, builtinIntlNumberFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlNumberFormat->setGlobalIntrinsicObject(state);
+    m_intlNumberFormatPrototype = m_intlNumberFormat->getFunctionPrototype(state).asObject();
+    m_intlNumberFormatPrototype->setGlobalIntrinsicObject(state, true);
+
+    formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlNumberFormatFormatGetter, 0, NativeFunctionInfo::Strict));
+    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
+                                                   ObjectPropertyDescriptor(JSGetterSetter(formatFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
+                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlNumberFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
+                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlNumberFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlNumberFormatPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                  ObjectPropertyDescriptor(Value(state.context()->staticStrings().Object.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlNumberFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
+                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlNumberFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlPluralRules = new NativeFunctionObject(state, NativeFunctionInfo(strings->PluralRules, builtinIntlPluralRulesConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlPluralRules->setGlobalIntrinsicObject(state);
+
+    m_intlPluralRulesPrototype = m_intlPluralRules->getFunctionPrototype(state).asObject();
+    m_intlPluralRulesPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_intlPluralRulesPrototype->defineOwnProperty(state, state.context()->staticStrings().select,
+                                                  ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->select, builtinIntlPluralRulesSelect, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlPluralRulesPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
+                                                  ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlPluralRulesResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlPluralRulesPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                 ObjectPropertyDescriptor(Value(state.context()->staticStrings().Object.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlPluralRules->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlPluralRulesSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+
+    m_intlLocale = new NativeFunctionObject(state, NativeFunctionInfo(strings->Locale, builtinIntlLocaleConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlLocale->setGlobalIntrinsicObject(state);
+
+    m_intlLocalePrototype = m_intlLocale->getFunctionPrototype(state).asObject();
+    m_intlLocalePrototype->setGlobalIntrinsicObject(state, true);
+
+    m_intlLocalePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                            ObjectPropertyDescriptor(Value(state.context()->staticStrings().intlDotLocale.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getBaseName, builtinIntlLocaleBaseNameGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().baseName), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCalendar, builtinIntlLocaleCalendarGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().calendar), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCaseFirst, builtinIntlLocaleCaseFirstGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().caseFirst), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCollation, builtinIntlLocaleCollationGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().collation), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getHourCycle, builtinIntlLocaleHourCycleGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().hourCycle), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getNumeric, builtinIntlLocaleNumericGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().numeric), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getNumberingSystem, builtinIntlLocaleNumberingSystemGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().numberingSystem), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getLanguage, builtinIntlLocaleLanguageGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().language), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getScript, builtinIntlLocaleScriptGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().script), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getRegion, builtinIntlLocaleRegionGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().region), desc);
+    }
+
+    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().toString,
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinIntlLocaleToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().maximize,
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->maximize, builtinIntlLocaleMaximize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().minimize,
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->minimize, builtinIntlLocaleMinimize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlRelativeTimeFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->RelativeTimeFormat, builtinIntlRelativeTimeFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_intlRelativeTimeFormat->setGlobalIntrinsicObject(state);
+
+    m_intlRelativeTimeFormatPrototype = m_intlRelativeTimeFormat->getFunctionPrototype(state).asObject();
+    m_intlRelativeTimeFormatPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_intlRelativeTimeFormatPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                        ObjectPropertyDescriptor(Value(state.context()->staticStrings().intlDotRelativeTimeFormat.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->format, builtinIntlRelativeTimeFormatFormat, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlRelativeTimeFormatFormatToParts, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlRelativeTimeFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intlRelativeTimeFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlRelativeTimeFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->Collator),
+                              ObjectPropertyDescriptor(m_intlCollator, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->DateTimeFormat),
+                              ObjectPropertyDescriptor(m_intlDateTimeFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->NumberFormat),
+                              ObjectPropertyDescriptor(m_intlNumberFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->PluralRules),
+                              ObjectPropertyDescriptor(m_intlPluralRules, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->Locale),
+                              ObjectPropertyDescriptor(m_intlLocale, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->RelativeTimeFormat),
+                              ObjectPropertyDescriptor(m_intlRelativeTimeFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    FunctionObject* getCanonicalLocales = new NativeFunctionObject(state, NativeFunctionInfo(strings->getCanonicalLocales, builtinIntlGetCanonicalLocales, 1, NativeFunctionInfo::Strict));
+    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->getCanonicalLocales),
+                              ObjectPropertyDescriptor(getCanonicalLocales, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
+
+#endif // ENABLE_ICU
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinIterator.cpp
new file mode 100644 (file)
index 0000000..33edc15
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return thisValue;
+}
+
+void GlobalObject::installIterator(ExecutionState& state)
+{
+    m_iteratorPrototype = new Object(state);
+    m_iteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-@@iterator
+    FunctionObject* fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinIteratorIterator, 0, NativeFunctionInfo::Strict));
+    m_iteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                          ObjectPropertyDescriptor(fn,
+                                                                                   (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinJSON.cpp
new file mode 100644 (file)
index 0000000..7f179ae
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/StringObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/TypedArrayObject.h"
+#include "runtime/BooleanObject.h"
+#include "runtime/BigIntObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag
+#define RAPIDJSON_ERROR_CHARTYPE char
+#include <rapidjson/document.h>
+#include <rapidjson/filereadstream.h>
+#include <rapidjson/memorystream.h>
+#include <rapidjson/internal/dtoa.h>
+#include <rapidjson/stringbuffer.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/error/en.h>
+
+namespace Escargot {
+
+template <typename Encoding>
+struct JSONStringStream {
+    typedef typename Encoding::Ch Ch;
+
+    JSONStringStream(const Ch* src, size_t length)
+        : src_(src)
+        , head_(src)
+        , tail_(src + length)
+    {
+    }
+
+    Ch Peek() const
+    {
+        if (UNLIKELY(tail_ <= src_)) {
+            return 0;
+        }
+        return *src_;
+    }
+    Ch Take()
+    {
+        if (UNLIKELY(tail_ <= src_)) {
+            return 0;
+        }
+        return *src_++;
+    }
+    size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+    Ch* PutBegin()
+    {
+        RAPIDJSON_ASSERT(false);
+        return 0;
+    }
+    void Put(Ch) { RAPIDJSON_ASSERT(false); }
+    void Flush() { RAPIDJSON_ASSERT(false); }
+    size_t PutEnd(Ch*)
+    {
+        RAPIDJSON_ASSERT(false);
+        return 0;
+    }
+
+    const Ch* src_; //!< Current read position.
+    const Ch* head_; //!< Original head of the string.
+    const Ch* tail_;
+};
+
+template <typename CharType, typename JSONCharType>
+static Value parseJSONWorker(ExecutionState& state, rapidjson::GenericValue<JSONCharType>& value)
+{
+    volatile int sp;
+    size_t currentStackBase = (size_t)&sp;
+#ifdef STACK_GROWS_DOWN
+    if (UNLIKELY(state.stackLimit() > currentStackBase)) {
+#else
+    if (UNLIKELY(state.stackLimit() < currentStackBase)) {
+#endif
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Maximum call stack size exceeded");
+    }
+
+    if (value.IsBool()) {
+        return Value(value.GetBool());
+    } else if (value.IsInt()) {
+        return Value(value.GetInt());
+    } else if (value.IsUint()) {
+        return Value(value.GetUint());
+    } else if (value.IsInt64()) {
+        return Value(value.GetInt64());
+    } else if (value.IsUint64()) {
+        return Value(value.GetUint64());
+    } else if (value.IsDouble()) {
+        return Value(value.GetDouble());
+    } else if (value.IsNull()) {
+        return Value(Value::Null);
+    } else if (value.IsString()) {
+        if (std::is_same<CharType, char16_t>::value) {
+            const char16_t* chars = (const char16_t*)value.GetString();
+            unsigned len = value.GetStringLength();
+            if (isAllLatin1(chars, len)) {
+                return new Latin1String(chars, len);
+            } else {
+                return new UTF16String(chars, len);
+            }
+        } else {
+            const char* valueAsString = (const char*)value.GetString();
+            if (isAllASCII(valueAsString, strlen(valueAsString))) {
+                return new ASCIIString(valueAsString);
+            } else {
+                return new UTF16String(utf8StringToUTF16String(valueAsString, strlen(valueAsString)));
+            }
+        }
+    } else if (value.IsArray()) {
+        ArrayObject* arr = new ArrayObject(state, value.Size(), false);
+        for (size_t i = 0; i < value.Size(); i++) {
+            arr->defineOwnIndexedPropertyWithExpandedLength(state, i, parseJSONWorker<CharType, JSONCharType>(state, value[i]));
+        }
+        return arr;
+    } else if (value.IsObject()) {
+        Object* obj = new Object(state);
+        if (value.MemberCount() > ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE) {
+            obj->markThisObjectDontNeedStructureTransitionTable();
+        }
+        auto iter = value.MemberBegin();
+        while (iter != value.MemberEnd()) {
+            Value propertyName = parseJSONWorker<CharType, JSONCharType>(state, iter->name);
+            ASSERT(propertyName.isString());
+            obj->defineOwnProperty(state, ObjectPropertyName(AtomicString(state, propertyName.toString(state))),
+                                   ObjectPropertyDescriptor(parseJSONWorker<CharType, JSONCharType>(state, iter->value), ObjectPropertyDescriptor::AllPresent));
+            iter++;
+        }
+        return obj;
+    } else {
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+template <typename CharType, typename JSONCharType>
+static Value parseJSON(ExecutionState& state, const CharType* data, size_t length)
+{
+    auto strings = &state.context()->staticStrings();
+    rapidjson::GenericDocument<JSONCharType> jsonDocument;
+
+    JSONStringStream<JSONCharType> stringStream(data, length);
+    jsonDocument.ParseStream(stringStream);
+    if (jsonDocument.HasParseError()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, strings->JSON.string(), true, strings->parse.string(), rapidjson::GetParseError_En(jsonDocument.GetParseError()));
+    }
+
+    return parseJSONWorker<CharType, JSONCharType>(state, jsonDocument);
+}
+
+String* codePointTo4digitString(int codepoint)
+{
+    StringBuilder ret;
+    int d = 16 * 16 * 16;
+    for (int i = 0; i < 4; ++i) {
+        if (codepoint >= d) {
+            char16_t c;
+            if (codepoint / d < 10) {
+                c = (codepoint / d) + '0';
+            } else {
+                c = (codepoint / d) - 10 + 'a';
+            }
+            codepoint %= d;
+            ret.appendChar(c);
+        } else {
+            ret.appendChar('0');
+        }
+        d >>= 4;
+    }
+
+    return ret.finalize();
+}
+
+static Value builtinJSONParse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+
+    // 1, 2, 3
+    String* JText = argv[0].toString(state);
+    Value unfiltered;
+
+    if (JText->has8BitContent()) {
+        size_t len = JText->length();
+        char16_t* char16Buf = new char16_t[len];
+        std::unique_ptr<char16_t[]> buf(char16Buf);
+        const LChar* srcBuf = JText->characters8();
+        for (size_t i = 0; i < len; i++) {
+            char16Buf[i] = srcBuf[i];
+        }
+        unfiltered = parseJSON<char16_t, rapidjson::UTF16<char16_t>>(state, buf.get(), JText->length());
+    } else {
+        unfiltered = parseJSON<char16_t, rapidjson::UTF16<char16_t>>(state, JText->characters16(), JText->length());
+    }
+
+    // 4
+    Value reviver = argv[1];
+    if (reviver.isCallable()) {
+        Object* root = new Object(state);
+        root->markThisObjectDontNeedStructureTransitionTable();
+        root->defineOwnProperty(state, ObjectPropertyName(state, String::emptyString), ObjectPropertyDescriptor(unfiltered, ObjectPropertyDescriptor::AllPresent));
+        std::function<Value(Value, const ObjectPropertyName&)> Walk;
+        Walk = [&](Value holder, const ObjectPropertyName& name) -> Value {
+            Value val = holder.asPointerValue()->asObject()->get(state, name).value(state, holder);
+            if (val.isObject()) {
+                if (val.asObject()->isArray(state)) {
+                    Object* object = val.asObject();
+                    uint32_t i = 0;
+                    uint32_t len = object->length(state);
+                    while (i < len) {
+                        Value newElement = Walk(val, ObjectPropertyName(state, Value(i).toString(state)));
+                        if (newElement.isUndefined()) {
+                            object->deleteOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)));
+                        } else {
+                            object->defineOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)), ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
+                        }
+                        i++;
+                    }
+                } else if (val.asObject()->isTypedArrayObject()) {
+                    ArrayBufferView* arrObject = val.asObject()->asArrayBufferView();
+                    uint32_t i = 0;
+                    uint32_t len = arrObject->arrayLength();
+                    while (i < len) {
+                        Value newElement = Walk(val, ObjectPropertyName(state, Value(i).toString(state)));
+                        if (newElement.isUndefined()) {
+                            arrObject->deleteOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)));
+                        } else {
+                            arrObject->defineOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)), ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
+                        }
+                        i++;
+                    }
+                } else {
+                    Object* object = val.asObject();
+
+                    ObjectPropertyNameVector keys;
+                    if (!object->canUseOwnPropertyKeysFastPath()) {
+                        auto keyValues = Object::enumerableOwnProperties(state, object, EnumerableOwnPropertiesType::Key);
+
+                        for (size_t i = 0; i < keyValues.size(); ++i) {
+                            keys.push_back(ObjectPropertyName(state, keyValues[i]));
+                        }
+                    } else {
+                        object->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& P, const ObjectStructurePropertyDescriptor& desc, void* data) -> bool {
+                            if (desc.isEnumerable()) {
+                                ObjectPropertyNameVector* keys = (ObjectPropertyNameVector*)data;
+                                keys->push_back(P);
+                            }
+                            return true;
+                        },
+                                            &keys);
+                    }
+
+                    for (auto key : keys) {
+                        Value newElement = Walk(val, key);
+                        if (newElement.isUndefined()) {
+                            object->deleteOwnProperty(state, key);
+                        } else {
+                            object->defineOwnProperty(state, key, ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
+                        }
+                    }
+                }
+            }
+            Value arguments[] = { name.toPlainValue(state), val };
+            return Object::call(state, reviver, holder, 2, arguments);
+        };
+        return Walk(root, ObjectPropertyName(state, String::emptyString));
+    }
+
+    // 5
+    return unfiltered;
+}
+
+static void builtinJSONArrayReplacerHelper(ExecutionState& state, ValueVectorWithInlineStorage& propertyList, Value property)
+{
+    String* item;
+
+    if (property.isString()) {
+        item = property.asString();
+    } else if (property.isNumber()) {
+        item = property.toString(state);
+    } else if (property.isObject() && (property.asPointerValue()->isStringObject() || property.asPointerValue()->isNumberObject())) {
+        item = property.toString(state);
+    } else {
+        return;
+    }
+
+    for (size_t i = 0; i < propertyList.size(); i++) {
+        if (propertyList[i].abstractEqualsTo(state, item)) {
+            return;
+        }
+    }
+    propertyList.push_back(Value(item));
+}
+
+static bool builtinJSONStringifyStr(ExecutionState& state, Value key, Object* holder,
+                                    StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
+                                    String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
+                                    LargeStringBuilder& product);
+static void builtinJSONStringifyJA(ExecutionState& state, Object* obj,
+                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
+                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
+                                   LargeStringBuilder& product);
+static void builtinJSONStringifyJO(ExecutionState& state, Object* value,
+                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
+                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
+                                   LargeStringBuilder& product);
+static void builtinJSONStringifyQuote(ExecutionState& state, Value value, LargeStringBuilder& product);
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonproperty
+static bool builtinJSONStringifyStr(ExecutionState& state, Value key, Object* holder,
+                                    StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack,
+                                    String* indent, String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
+                                    LargeStringBuilder& product)
+{
+    Value value = holder->get(state, ObjectPropertyName(state, key)).value(state, holder);
+    if (value.isObject() || value.isBigInt()) {
+        Value toJson = Object::getV(state, value, ObjectPropertyName(state, strings->toJSON));
+        if (toJson.isCallable()) {
+            Value arguments[] = { key.toString(state) };
+            value = Object::call(state, toJson, value, 1, arguments);
+        }
+    }
+
+    if (!replacerFunc.isUndefined()) {
+        Value arguments[] = { key.toString(state), value };
+        value = Object::call(state, replacerFunc, holder, 2, arguments);
+    }
+
+    if (value.isObject()) {
+        if (value.asObject()->isNumberObject()) {
+            value = Value(value.toNumber(state));
+        } else if (value.asObject()->isStringObject()) {
+            value = Value(value.toString(state));
+        } else if (value.asObject()->isBooleanObject()) {
+            value = Value(value.asObject()->asBooleanObject()->primitiveValue());
+        } else if (value.asObject()->isBigIntObject()) {
+            value = Value(value.asObject()->asBigIntObject()->primitiveValue());
+        }
+    }
+    if (value.isNull()) {
+        product.appendString(strings->null.string());
+        return true;
+    }
+    if (value.isBoolean()) {
+        product.appendString(value.asBoolean() ? strings->stringTrue.string() : strings->stringFalse.string());
+        return true;
+    }
+    if (value.isString()) {
+        builtinJSONStringifyQuote(state, value.asString(), product);
+        return true;
+    }
+    if (value.isNumber()) {
+        double d = value.toNumber(state);
+        if (std::isfinite(d)) {
+            product.appendString(value.toString(state));
+            return true;
+        }
+        product.appendString(strings->null.string());
+        return true;
+    }
+    if (value.isBigInt()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Could not serialize a BigInt");
+    }
+    if (value.isObject() && !value.isCallable()) {
+        if (value.asObject()->isArray(state)) {
+            builtinJSONStringifyJA(state, value.asObject(), strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
+        } else {
+            builtinJSONStringifyJO(state, value.asObject(), strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
+        }
+        return true;
+    }
+
+    return false;
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonarray
+static void builtinJSONStringifyJA(ExecutionState& state, Object* obj,
+                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack,
+                                   String* indent, String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
+                                   LargeStringBuilder& product)
+{
+    // 1
+    for (size_t i = 0; i < stack.size(); i++) {
+        Value& v = stack[i];
+        if (v == Value(obj)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JAError);
+        }
+    }
+    // 2
+    stack.push_back(Value(obj));
+    // 3
+    String* stepback = indent;
+    // 4
+    StringBuilder newIndent;
+    newIndent.appendString(indent);
+    newIndent.appendString(gap);
+    indent = newIndent.finalize(&state);
+
+    // 6, 7
+    uint32_t len = obj->length(state);
+
+    // Each array element requires at least 1 character for the value, and 1 character for the separator
+    if (len / 2 > STRING_MAXIMUM_LENGTH) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JAError);
+    }
+
+    // 8 ~ 9
+    uint32_t index = 0;
+    bool first = true;
+    String* seperator = strings->asciiTable[(size_t)','].string();
+
+    product.appendChar('[');
+    while (index < len) {
+        if (first) {
+            if (gap->length()) {
+                product.appendChar('\n');
+                product.appendString(indent);
+                StringBuilder seperatorBuilder;
+                seperatorBuilder.appendChar(',');
+                seperatorBuilder.appendChar('\n');
+                seperatorBuilder.appendString(indent);
+                seperator = seperatorBuilder.finalize(&state);
+            }
+            first = false;
+        } else {
+            product.appendString(seperator);
+        }
+
+        bool strP = builtinJSONStringifyStr(state, Value(index), obj, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
+        if (!strP) {
+            product.appendString(strings->null.string());
+        }
+        index++;
+    }
+
+    if (!first && gap->length()) {
+        product.appendChar('\n');
+        product.appendString(stepback);
+    }
+
+    product.appendChar(']');
+
+    // 11
+    stack.pop_back();
+    // 12
+    indent = stepback;
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonobject
+static void builtinJSONStringifyJO(ExecutionState& state, Object* value,
+                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
+                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList, LargeStringBuilder& product)
+{
+    // 1
+    for (size_t i = 0; i < stack.size(); i++) {
+        if (stack[i] == value) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JOError);
+        }
+    }
+    // 2
+    stack.push_back(Value(value));
+    // 3
+    String* stepback = indent;
+    // 4
+    StringBuilder newIndent;
+    newIndent.appendString(indent);
+    newIndent.appendString(gap);
+    indent = newIndent.finalize(&state);
+    // 5, 6
+    ValueVectorWithInlineStorage k;
+    if (propertyListTouched) {
+        k = propertyList;
+    } else {
+        k = Object::enumerableOwnProperties(state, value, EnumerableOwnPropertiesType::Key);
+    }
+
+    // 7 ~ 9
+    bool first = true;
+    size_t len = k.size();
+    String* seperator = strings->asciiTable[(size_t)','].string();
+
+    product.appendChar('{');
+    LargeStringBuilder subProduct;
+    for (size_t i = 0; i < len; i++) {
+        auto strP = builtinJSONStringifyStr(state, k[i], value, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, subProduct);
+        if (strP) {
+            if (first) {
+                if (gap->length()) {
+                    product.appendChar('\n');
+                    product.appendString(indent);
+                    StringBuilder seperatorBuilder;
+                    seperatorBuilder.appendChar(',');
+                    seperatorBuilder.appendChar('\n');
+                    seperatorBuilder.appendString(indent);
+                    seperator = seperatorBuilder.finalize(&state);
+                }
+                first = false;
+            } else {
+                product.appendString(seperator);
+            }
+
+            builtinJSONStringifyQuote(state, k[i], product);
+            product.appendChar(':');
+            if (gap->length() != 0) {
+                product.appendChar(' ');
+            }
+            product.appendStringBuilder(subProduct);
+            subProduct.clear();
+        }
+    }
+
+    if (!first && gap->length()) {
+        product.appendChar('\n');
+        product.appendString(stepback);
+    }
+
+    product.appendChar('}');
+
+    // 11
+    stack.pop_back();
+    // 12
+    indent = stepback;
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-quotejsonstring
+static void builtinJSONStringifyQuote(ExecutionState& state, String* value, LargeStringBuilder& product)
+{
+    auto bad = value->bufferAccessData();
+    product.appendChar('"');
+    for (size_t i = 0; i < bad.length; ++i) {
+        char16_t c = bad.charAt(i);
+
+        switch (c) {
+        case u'\"':
+        case u'\\':
+            product.appendChar('\\');
+            product.appendChar(c);
+            break;
+        case u'\b':
+            product.appendChar('\\');
+            product.appendChar('b');
+            break;
+        case u'\f':
+            product.appendChar('\\');
+            product.appendChar('f');
+            break;
+        case u'\n':
+            product.appendChar('\\');
+            product.appendChar('n');
+            break;
+        case u'\r':
+            product.appendChar('\\');
+            product.appendChar('r');
+            break;
+        case u'\t':
+            product.appendChar('\\');
+            product.appendChar('t');
+            break;
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+        case 11:
+        case 14:
+        case 15:
+        case 16:
+        case 17:
+        case 18:
+        case 19:
+        case 20:
+        case 21:
+        case 22:
+        case 23:
+        case 24:
+        case 25:
+        case 26:
+        case 27:
+        case 28:
+        case 29:
+        case 30:
+        case 31:
+            product.appendChar('\\');
+            product.appendChar('u');
+            product.appendString(codePointTo4digitString(c));
+            break;
+        default:
+            product.appendChar(c);
+        }
+    }
+    product.appendChar('"');
+}
+
+static void builtinJSONStringifyQuote(ExecutionState& state, Value value, LargeStringBuilder& product)
+{
+    String* str = value.toString(state);
+    builtinJSONStringifyQuote(state, str, product);
+}
+
+static Value builtinJSONStringify(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+
+    // 1, 2, 3
+    Value value = argv[0];
+    Value replacer = argv[1];
+    Value space = argv[2];
+    String* indent = String::emptyString;
+    ValueVectorWithInlineStorage stack;
+    ValueVectorWithInlineStorage propertyList;
+    bool propertyListTouched = false;
+
+    // 4
+    Value replacerFunc;
+    if (replacer.isObject()) {
+        if (replacer.isCallable()) {
+            replacerFunc = replacer;
+        } else if (replacer.asObject()->isArrayObject()) {
+            propertyListTouched = true;
+            ArrayObject* arrObject = replacer.asObject()->asArrayObject();
+
+            std::vector<Value::ValueIndex> indexes;
+            arrObject->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& P, const ObjectStructurePropertyDescriptor& desc, void* data) -> bool {
+                Value::ValueIndex idx = P.toPlainValue(state).toNumber(state);
+                if (idx != Value::InvalidIndexValue) {
+                    std::vector<Value::ValueIndex>* indexes = (std::vector<Value::ValueIndex>*)data;
+                    indexes->push_back(idx);
+                }
+                return true;
+            },
+                                   &indexes);
+            std::sort(indexes.begin(), indexes.end(), std::less<Value::ValueIndex>());
+            for (uint32_t i = 0; i < indexes.size(); ++i) {
+                Value property = arrObject->get(state, ObjectPropertyName(state, Value(indexes[i]))).value(state, arrObject);
+                builtinJSONArrayReplacerHelper(state, propertyList, property);
+            }
+        } else if (replacer.asObject()->isArray(state)) {
+            propertyListTouched = true;
+            Object* replacerObj = replacer.asObject();
+            uint64_t len = replacerObj->length(state);
+            uint64_t k = 0;
+
+            while (k < len) {
+                Value v = replacerObj->getIndexedProperty(state, Value(k)).value(state, replacerObj);
+                builtinJSONArrayReplacerHelper(state, propertyList, v);
+                k++;
+            }
+        }
+    }
+
+    // 5
+    if (space.isObject()) {
+        if (space.isPointerValue() && space.asPointerValue()->isNumberObject()) {
+            space = Value(space.toNumber(state));
+        } else if (space.isPointerValue() && space.asPointerValue()->isStringObject()) {
+            space = space.toString(state);
+        }
+    }
+
+    // 6, 7, 8
+    String* gap = String::emptyString;
+    if (space.isNumber()) {
+        int space_cnt = std::min(space.toInteger(state), 10.0);
+        if (space_cnt >= 1) {
+            UTF8StringData gapData;
+            gapData.resizeWithUninitializedValues(space_cnt);
+            for (int i = 0; i < space_cnt; i++) {
+                gapData[i] = ' ';
+            }
+            gap = new ASCIIString(gapData.data(), gapData.length());
+        }
+    } else if (space.isString()) {
+        if (space.asString()->length() <= 10) {
+            gap = space.asString();
+        } else {
+            gap = space.asString()->substring(0, 10);
+        }
+    }
+
+    // 9
+    Object* wrapper = new Object(state);
+    // 10
+    wrapper->defineOwnProperty(state, ObjectPropertyName(state, String::emptyString), ObjectPropertyDescriptor(value, ObjectPropertyDescriptor::AllPresent));
+    LargeStringBuilder product;
+    auto ret = builtinJSONStringifyStr(state, String::emptyString, wrapper, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
+    if (ret) {
+        return product.finalize(&state);
+    }
+    return Value();
+}
+
+void GlobalObject::installJSON(ExecutionState& state)
+{
+    m_json = new Object(state);
+    m_json->setGlobalIntrinsicObject(state);
+    m_json->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                             ObjectPropertyDescriptor(Value(state.context()->staticStrings().JSON.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().JSON),
+                      ObjectPropertyDescriptor(m_json, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_jsonParse = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().parse, builtinJSONParse, 2, NativeFunctionInfo::Strict));
+    m_json->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parse),
+                              ObjectPropertyDescriptor(m_jsonParse,
+                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_jsonStringify = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringify, builtinJSONStringify, 3, NativeFunctionInfo::Strict));
+    m_json->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringify),
+                              ObjectPropertyDescriptor(m_jsonStringify,
+                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMap.cpp
new file mode 100644 (file)
index 0000000..d509e13
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/MapObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinMapConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    // Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
+    // Set map's [[MapData]] internal slot to a new empty List.
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->mapPrototype();
+    });
+    MapObject* map = new MapObject(state, proto);
+
+    // If iterable is not present, or is either undefined or null, return map.
+    if (argc == 0 || argv[0].isUndefinedOrNull()) {
+        return map;
+    }
+
+    Value iterable = argv[0];
+
+    // Let adder be ? Get(map, "set").
+    Value adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map);
+    // If IsCallable(adder) is false, throw a TypeError exception.
+    if (!adder.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
+    }
+
+    // Let iteratorRecord be ? GetIterator(iterable).
+    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
+    while (true) {
+        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
+        if (!next.hasValue()) {
+            return map;
+        }
+
+        Value nextItem = IteratorObject::iteratorValue(state, next.value());
+        if (!nextItem.isObject()) {
+            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
+            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
+        }
+
+        try {
+            // Let k be Get(nextItem, "0").
+            // If k is an abrupt completion, return ? IteratorClose(iter, k).
+            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
+            // Let v be Get(nextItem, "1").
+            // If v is an abrupt completion, return ? IteratorClose(iter, v).
+            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
+
+            // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »).
+            Value argv[2] = { k, v };
+            Object::call(state, adder, map, 2, argv);
+        } catch (const Value& v) {
+            // we should save thrown value bdwgc cannot track thrown value
+            Value exceptionValue = v;
+            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
+            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+        }
+    }
+
+    return map;
+}
+
+#define RESOLVE_THIS_BINDING_TO_MAP(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                          \
+    if (!thisValue.isObject() || !thisValue.asObject()->isMapObject()) {                                                                                                                                                                                 \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                    \
+    MapObject* NAME = thisValue.asObject()->asMapObject();
+
+static Value builtinMapClear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, clear);
+    M->clear(state);
+    return Value();
+}
+
+static Value builtinMapDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, stringDelete);
+    return Value(M->deleteOperation(state, argv[0]));
+}
+
+static Value builtinMapGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, get);
+    return M->get(state, argv[0]);
+}
+
+static Value builtinMapHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, has);
+    return Value(M->has(state, argv[0]));
+}
+
+static Value builtinMapSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, set);
+    M->set(state, argv[0], argv[1]);
+    return M;
+}
+
+static Value builtinMapForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, forEach);
+    // Let M be the this value.
+    // If Type(M) is not Object, throw a TypeError exception.
+    // If M does not have a [[MapData]] internal slot, throw a TypeError exception.
+
+    Value callbackfn = argv[0];
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Map.string(), true, state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc >= 2) {
+        T = argv[1];
+    }
+    // Let entries be the List that is the value of M's [[MapData]] internal slot.
+    const MapObject::MapObjectData& entries = M->storage();
+    // Repeat for each Record {[[Key]], [[Value]]} e that is an element of entries, in original key insertion order
+    for (size_t i = 0; i < entries.size(); i++) {
+        // If e.[[Key]] is not empty, then
+        if (!entries[i].first.isEmpty()) {
+            // Perform ? Call(callbackfn, T, « e.[[Value]], e.[[Key]], M »).
+            Value argv[3] = { Value(entries[i].second), Value(entries[i].first), Value(M) };
+            Object::call(state, callbackfn, T, 3, argv);
+        }
+    }
+
+    return Value();
+}
+
+static Value builtinMapKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, keys);
+    return M->keys(state);
+}
+
+static Value builtinMapValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, values);
+    return M->values(state);
+}
+
+static Value builtinMapEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, entries);
+    return M->entries(state);
+}
+
+static Value builtinMapSizeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_MAP(M, Map, size);
+    return Value(M->size(state));
+}
+
+static Value builtinMapIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isMapIteratorObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().MapIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    MapIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asMapIteratorObject();
+    return iter->next(state);
+}
+
+void GlobalObject::installMap(ExecutionState& state)
+{
+    m_map = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Map, builtinMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_map->setGlobalIntrinsicObject(state);
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_map->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    m_mapPrototype = new MapObject(state, m_objectPrototype);
+    m_mapPrototype->setGlobalIntrinsicObject(state, true);
+    m_mapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clear),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinMapClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinMapDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinMapGet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinMapHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinMapSet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinMapForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keys, builtinMapKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinMapValues, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    auto entFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinMapEntries, 0, NativeFunctionInfo::Strict));
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
+                                                     ObjectPropertyDescriptor(entFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                     ObjectPropertyDescriptor(entFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                     ObjectPropertyDescriptor(Value(state.context()->staticStrings().Map.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    JSGetterSetter gs(
+        new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSize, builtinMapSizeGetter, 0, NativeFunctionInfo::Strict)),
+        Value(Value::EmptyValue));
+    ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+    m_mapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);
+
+    m_mapIteratorPrototype = new Object(state, m_iteratorPrototype);
+    m_mapIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_mapIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinMapIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_mapIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                             ObjectPropertyDescriptor(Value(String::fromASCII("Map Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    m_map->setFunctionPrototype(state, m_mapPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Map),
+                      ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinMath.cpp
new file mode 100644 (file)
index 0000000..e54ae9f
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/ThreadLocal.h"
+#include "runtime/StringObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+#include "runtime/IEEE754.h"
+#include <math.h>
+
+namespace Escargot {
+
+static Value builtinMathAbs(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return Value(std::abs(argv[0].toNumber(state)));
+}
+
+static Value builtinMathMax(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    bool is_NaN = false;
+    if (argc == 0) {
+        double n_inf = -1 * std::numeric_limits<double>::infinity();
+        return Value(n_inf);
+    }
+
+    double maxValue = argv[0].toNumber(state);
+    for (unsigned i = 1; i < argc; i++) {
+        double value = argv[i].toNumber(state);
+        if (std::isnan(value))
+            is_NaN = true;
+        if (value > maxValue || (!value && !maxValue && !std::signbit(value)))
+            maxValue = value;
+    }
+    if (is_NaN) {
+        double qnan = std::numeric_limits<double>::quiet_NaN();
+        return Value(qnan);
+    }
+    return Value(maxValue);
+}
+
+static Value builtinMathMin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (argc == 0) {
+        return Value(std::numeric_limits<double>::infinity());
+    }
+
+    bool hasNaN = false;
+    double minValue = argv[0].toNumber(state);
+    for (unsigned i = 1; i < argc; i++) {
+        double value = argv[i].toNumber(state);
+        if (std::isnan(value)) {
+            hasNaN = true;
+        }
+        if (value < minValue || (!value && !minValue && std::signbit(value))) {
+            minValue = value;
+        }
+    }
+    if (hasNaN) {
+        double qnan = std::numeric_limits<double>::quiet_NaN();
+        return Value(qnan);
+    }
+    return Value(minValue);
+}
+
+static Value builtinMathRound(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    if (x == static_cast<int64_t>(x)) {
+        return Value(x);
+    }
+    if (x == -0.5)
+        return Value(-0.0);
+    else if (x > -0.5)
+        return Value(round(x));
+    else
+        return Value(floor(x + 0.5));
+}
+
+static Value builtinMathSin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value x = argv[0];
+    return Value(ieee754::sin(x.toNumber(state)));
+}
+
+static Value builtinMathSinh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::sinh(x));
+}
+
+static Value builtinMathCos(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value x = argv[0];
+    return Value(ieee754::cos(x.toNumber(state)));
+}
+
+static Value builtinMathCosh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::cosh(x));
+}
+
+static Value builtinMathAcos(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::acos(x));
+}
+
+static Value builtinMathAcosh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::acosh(x));
+}
+
+static Value builtinMathAsin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::asin(x));
+}
+
+static Value builtinMathAsinh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::asinh(x));
+}
+
+static Value builtinMathAtan(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::atan(x));
+}
+
+static Value builtinMathAtan2(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double y = argv[0].toNumber(state);
+    double x = argv[1].toNumber(state);
+    return Value(ieee754::atan2(y, x));
+}
+
+static Value builtinMathAtanh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::atanh(x));
+}
+
+static Value builtinMathTan(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::tan(x));
+}
+
+static Value builtinMathTanh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::tanh(x));
+}
+
+static Value builtinMathTrunc(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(trunc(x));
+}
+
+static Value builtinMathSign(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    if (std::isnan(x))
+        return Value(std::numeric_limits<double>::quiet_NaN());
+    else if (x == 0.0) {
+        if (std::signbit(x)) {
+            return Value(Value::EncodeAsDouble, -0.0);
+        } else {
+            return Value(0);
+        }
+    } else if (std::signbit(x))
+        return Value(-1);
+    else
+        return Value(1);
+}
+
+static Value builtinMathSqrt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value x = argv[0];
+    return Value(sqrt(x.toNumber(state)));
+}
+
+static Value builtinMathPow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    double y = argv[1].toNumber(state);
+    if (UNLIKELY(std::isnan(y)))
+        return Value(std::numeric_limits<double>::quiet_NaN());
+    if (UNLIKELY(std::abs(x) == 1 && std::isinf(y)))
+        return Value(std::numeric_limits<double>::quiet_NaN());
+
+    int y_int = static_cast<int>(y);
+
+    if (y == y_int) {
+        unsigned n = (y < 0) ? -y : y;
+        double m = x;
+        double p = 1;
+        while (true) {
+            if ((n & 1) != 0)
+                p *= m;
+            n >>= 1;
+            if (n == 0) {
+                if (y < 0) {
+                    // Unfortunately, we have to be careful when p has reached
+                    // infinity in the computation, because sometimes the higher
+                    // internal precision in the pow() implementation would have
+                    // given us a finite p. This happens very rarely.
+
+                    double result = 1.0 / p;
+                    return (result == 0 && std::isinf(p)) ? Value(pow(x, static_cast<double>(y))) // Avoid pow(double, int).
+                                                          : Value(result);
+                }
+
+                return Value(p);
+            }
+            m *= m;
+        }
+    }
+
+    if (std::isinf(x)) {
+        if (x > 0) {
+            if (y > 0) {
+                return Value(std::numeric_limits<double>::infinity());
+            } else {
+                return Value(0.0);
+            }
+        } else {
+            if (y > 0) {
+                if (y == y_int && y_int % 2) { // odd
+                    return Value(-std::numeric_limits<double>::infinity());
+                } else {
+                    return Value(std::numeric_limits<double>::infinity());
+                }
+            } else {
+                if (y == y_int && y_int % 2) {
+                    return Value(-0.0);
+                } else {
+                    return Value(0.0);
+                }
+            }
+        }
+    }
+    // x == -0
+    if (1 / x == -std::numeric_limits<double>::infinity()) {
+        // y cannot be an odd integer because the case is filtered by "if (y_int == y)" above
+        if (y > 0) {
+            return Value(0);
+        } else if (y < 0) {
+            return Value(std::numeric_limits<double>::infinity());
+        }
+    }
+
+    if (y == 0.5) {
+        return Value(sqrt(x));
+    } else if (y == -0.5) {
+        return Value(1.0 / sqrt(x));
+    }
+
+    return Value(pow(x, y));
+}
+
+static Value builtinMathCbrt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::cbrt(x));
+}
+
+static Value builtinMathCeil(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+
+    // I add custom ceil implementation
+    // because I found some problem from gcc implementation about negative zero
+    return Value(ieee754::ceil(x));
+}
+
+static Value builtinMathClz32(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    uint32_t x = argv[0].toUint32(state);
+    int clz32 = 0;
+    for (int i = 31; i >= 0; i--) {
+        if (!(x >> i))
+            clz32++;
+        else
+            break;
+    }
+    return Value(clz32);
+}
+
+static Value builtinMathFloor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(floor(x));
+}
+
+static Value builtinMathFround(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(static_cast<double>(static_cast<float>(x)));
+}
+
+static Value builtinMathHypot(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double maxValue = 0;
+    bool has_nan = false;
+    bool has_inf = false;
+    for (unsigned i = 0; i < argc; i++) {
+        double value = argv[i].toNumber(state);
+        if (std::isinf(value)) {
+            has_inf = true;
+        } else if (std::isnan(value)) {
+            has_nan = true;
+        }
+        double absValue = std::abs(value);
+        maxValue = std::max(maxValue, absValue);
+    }
+    if (has_inf) {
+        return Value(std::numeric_limits<double>::infinity());
+    }
+
+    if (has_nan) {
+        double qnan = std::numeric_limits<double>::quiet_NaN();
+        return Value(qnan);
+    }
+
+    if (maxValue == 0) {
+        return Value(0.0);
+    }
+
+    double sum = 0;
+    double compensation = 0;
+    for (unsigned i = 0; i < argc; i++) {
+        double value = argv[i].toNumber(state);
+        double scaledArgument = value / maxValue;
+        double summand = scaledArgument * scaledArgument - compensation;
+        double preliminary = sum + summand;
+        compensation = (preliminary - sum) - summand;
+        sum = preliminary;
+    }
+    return Value(std::sqrt(sum) * maxValue);
+}
+
+static Value builtinMathIMul(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    int32_t x = argv[0].toInt32(state);
+    int32_t y = argv[1].toInt32(state);
+    return Value(x * y);
+}
+
+static Value builtinMathLog(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::log(x));
+}
+
+static Value builtinMathLog1p(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::log1p(x));
+}
+
+static Value builtinMathLog10(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::log10(x));
+}
+
+static Value builtinMathLog2(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::log2(x));
+}
+
+static Value builtinMathRandom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    std::uniform_real_distribution<double> distribution;
+    return Value(distribution(ThreadLocal::randEngine()));
+}
+
+static Value builtinMathExp(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::exp(x));
+}
+
+static Value builtinMathExpm1(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double x = argv[0].toNumber(state);
+    return Value(ieee754::expm1(x));
+}
+
+void GlobalObject::installMath(ExecutionState& state)
+{
+    m_math = new Object(state);
+    m_math->setGlobalIntrinsicObject(state);
+
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                             ObjectPropertyDescriptor(Value(state.context()->staticStrings().Math.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // initialize math object: $20.2.1.6 Math.PI
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_math->defineOwnPropertyThrowsException(state, strings->PI, ObjectPropertyDescriptor(Value(3.1415926535897932), ObjectPropertyDescriptor::ValuePresent));
+    // TODO(add reference)
+    m_math->defineOwnPropertyThrowsException(state, strings->E, ObjectPropertyDescriptor(Value(2.718281828459045), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.3
+    m_math->defineOwnPropertyThrowsException(state, strings->LN2, ObjectPropertyDescriptor(Value(0.6931471805599453), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.2
+    m_math->defineOwnPropertyThrowsException(state, strings->LN10, ObjectPropertyDescriptor(Value(2.302585092994046), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.4
+    m_math->defineOwnPropertyThrowsException(state, strings->LOG2E, ObjectPropertyDescriptor(Value(1.4426950408889634), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.5
+    m_math->defineOwnPropertyThrowsException(state, strings->LOG10E, ObjectPropertyDescriptor(Value(0.4342944819032518), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.7
+    m_math->defineOwnPropertyThrowsException(state, strings->SQRT1_2, ObjectPropertyDescriptor(Value(0.7071067811865476), ObjectPropertyDescriptor::ValuePresent));
+    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.8
+    m_math->defineOwnPropertyThrowsException(state, strings->SQRT2, ObjectPropertyDescriptor(Value(1.4142135623730951), ObjectPropertyDescriptor::ValuePresent));
+
+    // initialize math object: $20.2.2.1 Math.abs()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().abs),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().abs, builtinMathAbs, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.2 Math.acos()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().acos),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().acos, builtinMathAcos, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.3 Math.acosh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().acosh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().acosh, builtinMathAcosh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.4 Math.asin()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().asin),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asin, builtinMathAsin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.5 Math.asinh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().asinh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asinh, builtinMathAsinh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.6 Math.atan()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atan),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atan, builtinMathAtan, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.7 Math.atanh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atanh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atanh, builtinMathAtanh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.8 Math.atan2()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atan2),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atan2, builtinMathAtan2, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.9 Math.cbrt()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cbrt),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cbrt, builtinMathCbrt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.10 Math.ceil()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().ceil),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().ceil, builtinMathCeil, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.11 Math.clz32()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clz32),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clz32, builtinMathClz32, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.12 Math.cos()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cos),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cos, builtinMathCos, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.13 Math.cosh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cosh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cosh, builtinMathCosh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.14 Math.exp()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().exp),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().exp, builtinMathExp, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.15 Math.expm1()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().expm1),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().expm1, builtinMathExpm1, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.16 Math.floor()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().floor),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().floor, builtinMathFloor, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.17 Math.fround()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().fround),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().fround, builtinMathFround, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.18 Math.hypot()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().hypot),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().hypot, builtinMathHypot, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.19 Math.imul()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().imul),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().imul, builtinMathIMul, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // initialize math object: $20.2.2.20 Math.log()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log, builtinMathLog, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.21 Math.log1p()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log1p),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log1p, builtinMathLog1p, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.22 Math.log10()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log10),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log10, builtinMathLog10, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.23 Math.log2()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log2),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log2, builtinMathLog2, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.24 Math.max()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().max),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().max, builtinMathMax, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.25 Math.min()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().min),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().min, builtinMathMin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.26 Math.pow()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().pow),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().pow, builtinMathPow, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.27 Math.random()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().random),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().random, builtinMathRandom, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.28 Math.round()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().round),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().round, builtinMathRound, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.29 Math.sign()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sign),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sign, builtinMathSign, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.30 Math.sin()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sin),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sin, builtinMathSin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.31 Math.sinh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sinh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sinh, builtinMathSinh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.32 Math.sqrt()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sqrt),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sqrt, builtinMathSqrt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.33 Math.tan()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().tan),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().tan, builtinMathTan, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.34 Math.tanh()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().tanh),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().tanh, builtinMathTanh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // initialize math object: $20.2.2.35 Math.trunc()
+    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().trunc),
+                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().trunc, builtinMathTrunc, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Math),
+                      ObjectPropertyDescriptor(m_math, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinNumber.cpp
new file mode 100644 (file)
index 0000000..e74e11a
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/NumberObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+// dtoa
+#include "ieee.h"
+#include "double-conversion.h"
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+#include "intl/IntlNumberFormat.h"
+#endif
+
+#define NUMBER_TO_STRING_BUFFER_LENGTH 128
+
+namespace Escargot {
+
+static int itoa(int64_t value, char* sp, int radix)
+{
+    char tmp[256]; // be careful with the length of the buffer
+    char* tp = tmp;
+    int i;
+    uint64_t v;
+
+    int sign = (radix == 10 && value < 0);
+    if (sign) {
+        v = -value;
+    } else {
+        v = (uint64_t)value;
+    }
+
+    while (v || tp == tmp) {
+        i = v % radix;
+        v /= radix; // v/=radix uses less CPU clocks than v=v/radix does
+        if (i < 10) {
+            *tp++ = i + '0';
+        } else {
+            *tp++ = i + 'a' - 10;
+        }
+    }
+
+    int64_t len = tp - tmp;
+
+    if (sign) {
+        *sp++ = '-';
+        len++;
+    }
+
+    while (tp > tmp) {
+        *sp++ = *--tp;
+    }
+    *sp++ = 0;
+
+    return len;
+}
+
+static Value builtinNumberConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double num = 0;
+    if (argc > 0) {
+        if (UNLIKELY(argv[0].isBigInt())) {
+            num = argv[0].asBigInt()->toNumber();
+        } else {
+            num = argv[0].toNumber(state);
+        }
+    }
+
+    if (!newTarget.hasValue()) {
+        return Value(num);
+    } else {
+        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+            return constructorRealm->globalObject()->numberPrototype();
+        });
+        NumberObject* numObj = new NumberObject(state, proto, num);
+        return numObj;
+    }
+}
+
+static Value builtinNumberToFixed(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double number = 0.0;
+
+    if (thisValue.isNumber()) {
+        number = thisValue.asNumber();
+    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
+        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toFixed.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+
+    Value fractionDigits = argv[0];
+    int digit = fractionDigits.toInteger(state);
+    if (digit < 0 || digit > 100) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toFixed.string(), ErrorObject::Messages::GlobalObject_RangeError);
+    }
+
+    if (std::isnan(number)) {
+        return state.context()->staticStrings().NaN.string();
+    }
+
+    if (std::isinf(number)) {
+        if (number < 0) {
+            return state.context()->staticStrings().NegativeInfinity.string();
+        } else {
+            return state.context()->staticStrings().Infinity.string();
+        }
+    }
+
+    if (std::abs(number) >= pow(10, 21)) {
+        return Value(number).toString(state);
+    }
+
+    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
+    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
+    double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToFixed(number, digit, &builder);
+    return Value(new ASCIIString(builder.Finalize()));
+}
+
+static Value builtinNumberToExponential(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double number = 0.0;
+
+    if (thisValue.isNumber()) {
+        number = thisValue.asNumber();
+    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
+        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toExponential.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+
+    Value fractionDigits = argv[0];
+    int digit = fractionDigits.toInteger(state);
+
+    if (std::isnan(number)) { // 3
+        return state.context()->staticStrings().NaN.string();
+    }
+
+    if (std::isinf(number)) { // 6
+        if (number < 0) {
+            return state.context()->staticStrings().NegativeInfinity.string();
+        } else {
+            return state.context()->staticStrings().Infinity.string();
+        }
+    }
+
+    if (digit < 0 || digit > 100) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toExponential.string(), ErrorObject::Messages::GlobalObject_RangeError);
+    }
+
+    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
+    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
+    if (fractionDigits.isUndefined()) {
+        double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(number, -1, &builder);
+    } else {
+        double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(number, digit, &builder);
+    }
+    return Value(new ASCIIString(builder.Finalize()));
+}
+
+static Value builtinNumberToPrecision(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double number = 0.0;
+
+    if (thisValue.isNumber()) {
+        number = thisValue.asNumber();
+    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
+        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toPrecision.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+
+    Value precision = argv[0];
+    if (precision.isUndefined()) {
+        return Value(number).toString(state);
+    }
+
+    int p = precision.toInteger(state);
+
+    if (std::isnan(number)) {
+        return state.context()->staticStrings().NaN.string();
+    }
+
+    if (std::isinf(number)) {
+        if (number < 0) {
+            return state.context()->staticStrings().NegativeInfinity.string();
+        } else {
+            return state.context()->staticStrings().Infinity.string();
+        }
+    }
+
+    if (p < 1 || p > 100) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toPrecision.string(), ErrorObject::Messages::GlobalObject_RangeError);
+    }
+
+    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
+    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
+    double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(number, p, &builder);
+    return Value(new ASCIIString(builder.Finalize()));
+}
+
+static Value builtinNumberToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    double number = 0.0;
+
+    if (thisValue.isNumber()) {
+        number = thisValue.asNumber();
+    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
+        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+
+    double radix = 10;
+    if (argc > 0 && !argv[0].isUndefined()) {
+        radix = argv[0].toInteger(state);
+        if (radix < 2 || radix > 36) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_RadixInvalidRange);
+        }
+    }
+    if (std::isnan(number) || std::isinf(number)) {
+        return Value(number).toString(state);
+    }
+    if (radix == 10) {
+        return Value(number).toString(state);
+    }
+
+    bool isInteger = (static_cast<int64_t>(number) == number);
+    if (isInteger) {
+        bool minusFlag = (number < 0) ? 1 : 0;
+        number = (number < 0) ? (-1 * number) : number;
+        char buffer[256];
+        if (minusFlag) {
+            buffer[0] = '-';
+            itoa(static_cast<int64_t>(number), &buffer[1], radix);
+        } else {
+            itoa(static_cast<int64_t>(number), buffer, radix);
+        }
+        return new ASCIIString(buffer);
+    } else {
+        ASSERT(Value(number).isDouble());
+        NumberObject::RadixBuffer s;
+        const char* str = NumberObject::toStringWithRadix(state, s, number, radix);
+        return new ASCIIString(str);
+    }
+}
+
+static Value builtinNumberToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Number, toLocaleString);
+    if (!thisObject->isNumberObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    Value locales = argc > 0 ? argv[0] : Value();
+    Value options = argc > 1 ? argv[1] : Value();
+    Object* numberFormat = IntlNumberFormat::create(state, state.context(), locales, options);
+    double x = 0;
+    if (thisValue.isNumber()) {
+        x = thisValue.asNumber();
+    } else if (thisValue.isObject() && thisValue.asObject()->isNumberObject()) {
+        x = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    }
+    auto result = IntlNumberFormat::format(state, numberFormat, x);
+
+    return new UTF16String(result.data(), result.length());
+#else
+
+    ObjectGetResult toStrFuncGetResult = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toString));
+    if (toStrFuncGetResult.hasValue()) {
+        Value toStrFunc = toStrFuncGetResult.value(state, thisObject);
+        if (toStrFunc.isCallable()) {
+            // toLocaleString() ignores the first argument, unlike toString()
+            return Object::call(state, toStrFunc, thisObject, 0, argv);
+        }
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toLocaleString.string(), ErrorObject::Messages::GlobalObject_ToLocaleStringNotCallable);
+    RELEASE_ASSERT_NOT_REACHED();
+    return Value();
+#endif
+}
+
+static Value builtinNumberValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isNumber()) {
+        return Value(thisValue);
+    } else if (thisValue.isObject() && thisValue.asObject()->isNumberObject()) {
+        return Value(thisValue.asPointerValue()->asNumberObject()->primitiveValue());
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
+    RELEASE_ASSERT_NOT_REACHED();
+    return Value();
+}
+
+static Value builtinNumberIsFinite(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isNumber()) {
+        return Value(Value::False);
+    }
+
+    double number = argv[0].asNumber();
+    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
+        return Value(Value::False);
+    }
+    return Value(Value::True);
+}
+
+static Value builtinNumberIsInteger(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isNumber()) {
+        return Value(Value::False);
+    }
+
+    double number = argv[0].asNumber();
+    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
+        return Value(Value::False);
+    }
+
+    double integer = argv[0].toInteger(state);
+    if (number != integer) {
+        return Value(Value::False);
+    }
+    return Value(Value::True);
+}
+
+static Value builtinNumberIsNaN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isNumber()) {
+        return Value(Value::False);
+    }
+
+    double number = argv[0].asNumber();
+    if (std::isnan(number)) {
+        return Value(Value::True);
+    }
+    return Value(Value::False);
+}
+
+static Value builtinNumberIsSafeInteger(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isNumber()) {
+        return Value(Value::False);
+    }
+
+    double number = argv[0].asNumber();
+    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
+        return Value(Value::False);
+    }
+
+    double integer = argv[0].toInteger(state);
+    if (number != integer) {
+        return Value(Value::False);
+    }
+
+    if (std::abs(integer) <= 9007199254740991.0) {
+        return Value(Value::True);
+    }
+    return Value(Value::False);
+}
+
+void GlobalObject::installNumber(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_number = new NativeFunctionObject(state, NativeFunctionInfo(strings->Number, builtinNumberConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_number->setGlobalIntrinsicObject(state);
+
+    m_numberPrototype = new NumberObject(state, m_objectPrototype, 0);
+    m_numberPrototype->setGlobalIntrinsicObject(state, true);
+    m_number->setFunctionPrototype(state, m_numberPrototype);
+
+    m_numberPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinNumberToString, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleString),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleString, builtinNumberToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toFixed),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toFixed, builtinNumberToFixed, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toExponential),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toExponential, builtinNumberToExponential, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toPrecision),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toPrecision, builtinNumberToPrecision, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $20.1.3.26 Number.prototype.valueOf
+    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinNumberValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    m_number->setFunctionPrototype(state, m_numberPrototype);
+
+    ObjectPropertyDescriptor::PresentAttribute allFalsePresent = (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent
+                                                                                                              | ObjectPropertyDescriptor::NonEnumerablePresent
+                                                                                                              | ObjectPropertyDescriptor::NonConfigurablePresent);
+
+    // $20.1.2.1 Number.EPSILON
+    m_number->defineOwnPropertyThrowsException(state, strings->EPSILON, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::epsilon()), allFalsePresent));
+    // $20.1.2.2 Number.isFinite
+    m_number->defineOwnPropertyThrowsException(state, strings->isFinite,
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isFinite, builtinNumberIsFinite, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $20.1.2.3 Number.isInteger
+    m_number->defineOwnPropertyThrowsException(state, strings->isInteger,
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isInteger, builtinNumberIsInteger, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $20.1.2.3 Number.isNaN
+    m_number->defineOwnPropertyThrowsException(state, strings->isNaN,
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isNaN, builtinNumberIsNaN, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $20.1.2.5 Number.isSafeInteger
+    m_number->defineOwnPropertyThrowsException(state, strings->isSafeInteger,
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isSafeInteger, builtinNumberIsSafeInteger, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $20.1.2.6 Number.MAX_SAFE_INTEGER
+    m_number->defineOwnPropertyThrowsException(state, strings->MAX_SAFE_INTEGER, ObjectPropertyDescriptor(Value(9007199254740991.0), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
+    // $20.1.2.7 Number.MAX_VALUE
+    m_number->defineOwnPropertyThrowsException(state, strings->MAX_VALUE, ObjectPropertyDescriptor(Value(1.7976931348623157E+308), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
+    // $20.1.2.8 Number.MIN_SAFE_INTEGER
+    m_number->defineOwnPropertyThrowsException(state, strings->MIN_SAFE_INTEGER, ObjectPropertyDescriptor(Value(-9007199254740991.0), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
+    // $20.1.2.9 Number.MIN_VALUE
+    m_number->defineOwnPropertyThrowsException(state, strings->MIN_VALUE, ObjectPropertyDescriptor(Value(5E-324), allFalsePresent));
+    // $20.1.2.10 Number.NaN
+    m_number->defineOwnPropertyThrowsException(state, strings->NaN, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::quiet_NaN()), allFalsePresent));
+    // $20.1.2.11 Number.NEGATIVE_INFINITY
+    m_number->defineOwnPropertyThrowsException(state, strings->NEGATIVE_INFINITY, ObjectPropertyDescriptor(Value(-std::numeric_limits<double>::infinity()), allFalsePresent));
+    // $20.1.2.14 Number.POSITIVE_INFINITY
+    m_number->defineOwnPropertyThrowsException(state, strings->POSITIVE_INFINITY, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::infinity()), allFalsePresent));
+
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Number),
+                      ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinObject.cpp
new file mode 100644 (file)
index 0000000..f86b8a2
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/IteratorObject.h"
+
+namespace Escargot {
+
+typedef VectorWithInlineStorage<48, std::pair<ObjectPropertyName, ObjectStructurePropertyDescriptor>, GCUtil::gc_malloc_allocator<std::pair<ObjectPropertyName, ObjectStructurePropertyDescriptor>>> ObjectStructurePropertyVector;
+
+static Value builtinObject__proto__Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return thisValue.toObject(state)->getPrototype(state);
+}
+
+static Value builtinObject__proto__Setter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value value = argv[0];
+    Object* thisObject = thisValue.toObject(state);
+    // Setting __proto__ to a non-object, non-null value is ignored
+    if (!value.isObject() && !value.isNull()) {
+        return Value();
+    }
+    if (!thisObject->setPrototype(state, value)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "can't set prototype of this object");
+    }
+    return Value();
+}
+
+static Value builtinObjectConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is neither undefined nor the active function, then
+    if (newTarget.hasValue() && newTarget.value() != state.resolveCallee()) {
+        // Return ? OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
+        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+            return constructorRealm->globalObject()->objectPrototype();
+        });
+        return new Object(state, proto);
+    }
+
+    Value value = argv[0];
+    if (value.isUndefined() || value.isNull()) {
+        // If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
+        return new Object(state);
+    } else {
+        // Return ! ToObject(value).
+        return value.toObject(state);
+    }
+}
+
+static Value builtinObjectValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(ret, Object, valueOf);
+    return ret;
+}
+
+static Value builtinObjectPreventExtensions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return argv[0];
+    }
+    Object* o = argv[0].asObject();
+    if (!o->preventExtensions(state)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().preventExtensions.string(), "PreventExtensions is false");
+    }
+    return o;
+}
+
+static Value builtinObjectToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    StaticStrings* strings = &state.context()->staticStrings();
+
+    if (thisValue.isUndefined()) {
+        return strings->lazyObjectUndefinedToString().string();
+    } else if (thisValue.isNull()) {
+        return strings->lazyObjectNullToString().string();
+    }
+
+    Object* thisObject = thisValue.toObject(state);
+
+    // check isArray first
+    bool isArray = thisObject->isArray(state);
+
+    Value toStringTag = thisObject->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag)).value(state, thisObject);
+    if (toStringTag.isString()) {
+        String* tag = toStringTag.asString();
+        auto bad = tag->bufferAccessData();
+        if (bad.has8BitContent && bad.length < 256) {
+            LChar* buf = (LChar*)alloca(bad.length + 10);
+            size_t len = 0;
+
+            buf[0] = '[';
+            buf[1] = 'o';
+            buf[2] = 'b';
+            buf[3] = 'j';
+            buf[4] = 'e';
+            buf[5] = 'c';
+            buf[6] = 't';
+            buf[7] = ' ';
+            memcpy(buf + 8, bad.bufferAs8Bit, bad.length);
+            buf[bad.length + 8] = ']';
+            buf[bad.length + 9] = 0;
+            len = 9 + bad.length;
+
+            return AtomicString(state.context(), buf, len).string();
+        }
+
+        StringBuilder builder;
+        builder.appendString("[object ");
+        builder.appendString(tag);
+        builder.appendString("]");
+        return AtomicString(state, builder.finalize()).string();
+    }
+
+    if (isArray) {
+        return strings->lazyObjectArrayToString().string();
+    } else if (thisObject->isArgumentsObject()) {
+        return strings->lazyObjectArgumentsToString().string();
+    } else if (thisObject->isCallable()) {
+        return strings->lazyObjectFunctionToString().string();
+    } else if (thisObject->isErrorObject()) {
+        return strings->lazyObjectErrorToString().string();
+    } else if (thisObject->isBooleanObject()) {
+        return strings->lazyObjectBooleanToString().string();
+    } else if (thisObject->isNumberObject()) {
+        return strings->lazyObjectNumberToString().string();
+    } else if (thisObject->isStringObject()) {
+        return strings->lazyObjectStringToString().string();
+    } else if (thisObject->isDateObject()) {
+        return strings->lazyObjectDateToString().string();
+    } else if (thisObject->isRegExpObject()) {
+        return strings->lazyObjectRegExpToString().string();
+    }
+
+    return strings->lazyObjectObjectToString().string();
+}
+
+static Value builtinObjectHasOwnProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value key = argv[0].toPrimitive(state, Value::PrimitiveTypeHint::PreferString);
+    Object* obj = thisValue.toObject(state);
+    return Value(obj->hasOwnProperty(state, ObjectPropertyName(state, key)));
+}
+
+static Value objectDefineProperties(ExecutionState& state, Value object, Value properties)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    if (!object.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Object.string(), false, strings->defineProperty.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObject);
+    }
+
+    Object* O = object.asObject();
+    // Let props be ? ToObject(Properties).
+    Object* props = properties.toObject(state);
+
+    // Let keys be ? props.[[OwnPropertyKeys]]().
+    Object::OwnPropertyKeyVector keys = props->ownPropertyKeys(state);
+    // Let descriptors be a new empty List.
+    VectorWithInlineStorage<32, std::pair<ObjectPropertyName, ObjectPropertyDescriptor>, GCUtil::gc_malloc_allocator<std::pair<ObjectPropertyName, ObjectPropertyDescriptor>>> descriptors;
+
+    for (size_t i = 0; i < keys.size(); i++) {
+        // Let propDesc be ? props.[[GetOwnProperty]](nextKey).
+        ObjectPropertyName nextKey(state, keys[i]);
+        ObjectGetResult propDesc = props->getOwnProperty(state, nextKey);
+        // If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
+        if (propDesc.hasValue() && propDesc.isEnumerable()) {
+            // Let descObj be ? Get(props, nextKey).
+            Value descVal = propDesc.value(state, props);
+            if (!descVal.isObject()) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().defineProperty.string(), ErrorObject::Messages::GlobalObject_DescriptorNotObject);
+            }
+
+            // Let desc be ? ToPropertyDescriptor(descObj).
+            ObjectPropertyDescriptor desc(state, descVal.asObject());
+            // Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
+            descriptors.push_back(std::make_pair(nextKey, desc));
+        }
+    }
+
+    // For each pair from descriptors in list order, do
+    for (auto it : descriptors) {
+        // Let P be the first element of pair.
+        // Let desc be the second element of pair.
+        // Perform ? DefinePropertyOrThrow(O, P, desc).
+        O->defineOwnPropertyThrowsException(state, it.first, it.second);
+    }
+
+    return O;
+}
+
+static Value builtinObjectCreate(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject() && !argv[0].isNull())
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().create.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObjectAndNotNull);
+    Object* obj = new Object(state);
+    if (argv[0].isNull())
+        obj->setPrototype(state, Value(Value::Null));
+    else
+        obj->setPrototype(state, argv[0]);
+
+    if (!argv[1].isUndefined())
+        return objectDefineProperties(state, obj, argv[1]);
+    return obj;
+}
+
+static Value builtinObjectDefineProperties(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return objectDefineProperties(state, argv[0], argv[1]);
+}
+
+static Value builtinObjectDefineProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Object.defineProperty ( O, P, Attributes )
+    // If Type(O) is not Object, throw a TypeError exception.
+    if (!argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().defineProperty.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObject);
+    }
+    Object* O = argv[0].asObject();
+
+    // Let key be ToPropertyKey(P).
+    ObjectPropertyName key = ObjectPropertyName(state, argv[1]);
+
+    // Let desc be ToPropertyDescriptor(Attributes).
+    if (!argv[2].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Property description must be an object");
+    }
+
+    ObjectPropertyDescriptor desc(state, argv[2].asObject());
+
+    O->defineOwnPropertyThrowsException(state, key, desc);
+    return O;
+}
+
+static Value builtinObjectIsPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Object.prototype.isPrototypeOf (V)
+    // If V is not an object, return false.
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+    Value V = argv[0];
+
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, isPrototypeOf);
+
+    // Repeat
+    while (true) {
+        // Let V be the value of the [[Prototype]] internal property of V.
+        V = V.toObject(state)->getPrototype(state);
+        // if V is null, return false
+        if (!V.isObject())
+            return Value(false);
+        // If O and V refer to the same object, return true.
+        if (V.asObject() == O) {
+            return Value(true);
+        }
+    }
+}
+
+static Value builtinObjectPropertyIsEnumerable(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let P be toPropertyKey(V).
+    Value P = argv[0].toPropertyKey(state);
+
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, propertyIsEnumerable);
+
+    // Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument name.
+    ObjectGetResult desc = O->getOwnProperty(state, ObjectPropertyName(state, P));
+
+    // If desc is undefined, return false.
+    if (!desc.hasValue())
+        return Value(false);
+
+    // Return the value of desc.[[Enumerable]].
+    return Value(desc.isEnumerable());
+}
+
+static Value builtinObjectToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/#sec-object.prototype.tolocalestring
+    // Let O be the this value.
+    // Return ? Invoke(O, "toString").
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, toLocaleString);
+    Value toString = O->get(state, ObjectPropertyName(state.context()->staticStrings().toString)).value(state, thisValue);
+    return Object::call(state, toString, thisValue, 0, nullptr);
+}
+
+static Value builtinObjectGetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return argv[0].toObject(state)->getPrototype(state);
+}
+
+static Value builtinObjectSetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
+    // 19.1.2.18 Object.setPrototypeOf ( O, proto )
+    Value object = argv[0];
+    Value proto = argv[1];
+
+    // 1. Let O be RequireObjectCoercible(O).
+    // 2. ReturnIfAbrupt(O).
+    if (object.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "");
+        return Value();
+    }
+
+    // 3. If Type(proto) is neither Object nor Null, throw a TypeError exception.
+    if (!proto.isObject() && !proto.isNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "");
+        return Value();
+    }
+
+    // 4. If Type(O) is not Object, return O.
+    if (!object.isObject()) {
+        return object;
+    }
+
+    // 5. Let status be O.[[SetPrototypeOf]](proto).
+    Object* obj = object.toObject(state);
+    bool status = obj->setPrototype(state, proto);
+
+    // 7. If status is false, throw a TypeError exception.
+    if (!status) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "can't set prototype of this object");
+        return Value();
+    }
+
+    return object;
+}
+
+static Value builtinObjectFreeze(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        // If Type(O) is not Object, return O.
+        return argv[0];
+    }
+
+    Object* O = argv[0].asObject();
+
+    // Let status be ? SetIntegrityLevel(O, frozen).
+    // If status is false, throw a TypeError exception.
+    if (!Object::setIntegrityLevel(state, O, false)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().freeze.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+    }
+
+    // Return O.
+    return O;
+}
+
+static Value builtinObjectFromEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (argv[0].isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().fromEntries.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+    Value iterable = argv[0];
+    Object* obj = new Object(state);
+
+    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
+    while (true) {
+        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
+        if (!next.hasValue()) {
+            return obj;
+        }
+
+        Value nextItem = IteratorObject::iteratorValue(state, next.value());
+        if (!nextItem.isObject()) {
+            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
+            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
+        }
+
+        try {
+            // Let k be Get(nextItem, "0").
+            // If k is an abrupt completion, return ? IteratorClose(iter, k).
+            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
+            // Let v be Get(nextItem, "1").
+            // If v is an abrupt completion, return ? IteratorClose(iter, v).
+            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
+
+            ObjectPropertyName key(state, k);
+            obj->defineOwnPropertyThrowsException(state, key,
+                                                  ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+        } catch (const Value& v) {
+            // we should save thrown value bdwgc cannot track thrown value
+            Value exceptionValue = v;
+            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
+            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+        }
+    }
+
+    return obj;
+}
+
+// https://262.ecma-international.org/#sec-object.getownpropertydescriptor
+static Value builtinObjectGetOwnPropertyDescriptor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let obj be ToObject(O).
+    Object* O = argv[0].toObject(state);
+    // Let key be ? ToPropertyKey(P).
+    Value key = argv[1].toPropertyKey(state);
+
+    // Let desc be ? obj.[[GetOwnProperty]](key).
+    // Return FromPropertyDescriptor(desc).
+    return O->getOwnPropertyDescriptor(state, ObjectPropertyName(state, key));
+}
+
+// https://262.ecma-international.org/#sec-object.getownpropertydescriptors
+static Value builtinObjectGetOwnPropertyDescriptors(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Object* obj = argv[0].toObject(state);
+    auto ownKeys = obj->ownPropertyKeys(state);
+    Object* descriptors = new Object(state);
+
+    for (uint64_t i = 0; i < ownKeys.size(); i++) {
+        Value descriptor = obj->getOwnPropertyDescriptor(state, ObjectPropertyName(state, ownKeys[i]));
+        if (!descriptor.isUndefined()) {
+            descriptors->defineOwnProperty(state, ObjectPropertyName(state, ownKeys[i]), ObjectPropertyDescriptor(descriptor, ObjectPropertyDescriptor::AllPresent));
+        }
+    }
+    return descriptors;
+}
+
+enum class GetOwnPropertyKeysType {
+    String,
+    Symbol
+};
+
+static ArrayObject* getOwnPropertyKeys(ExecutionState& state, Value o, GetOwnPropertyKeysType type)
+{
+    // https://www.ecma-international.org/ecma-262/6.0/#sec-getownpropertykeys
+
+    // 1. Let obj be ToObject(O).
+    // 2. ReturnIfAbrupt(obj)
+    auto obj = o.asObject();
+    // 3. Let keys be obj.[[OwnPropertyKeys]]().
+    // 4. ReturnIfAbrupt(keys).
+    auto keys = obj->ownPropertyKeys(state);
+
+    // 5. Let nameList be a new empty List.
+    ValueVectorWithInlineStorage nameList;
+
+    // 6. Repeat for each element nextKey of keys in List order,
+    //  a. If Type(nextKey) is Type, then
+    //      i. Append nextKey as the last element of nameList.
+    bool (Escargot::Value::*func)() const;
+    if (type == GetOwnPropertyKeysType::String) {
+        func = &Value::isString;
+    } else {
+        func = &Value::isSymbol;
+    }
+    for (size_t i = 0; i < keys.size(); ++i) {
+        if ((keys[i].*func)()) {
+            nameList.pushBack(keys[i]);
+        }
+    }
+
+    // 7. Return CreateArrayFromList(nameList).
+    return Object::createArrayFromList(state, nameList.size(), nameList.data());
+}
+
+static Value builtinObjectGetOwnPropertyNames(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertynames
+    Object* O = argv[0].toObject(state);
+    return getOwnPropertyKeys(state, O, GetOwnPropertyKeysType::String);
+}
+
+static Value builtinObjectGetOwnPropertySymbols(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertysymbols
+    Object* O = argv[0].toObject(state);
+    return getOwnPropertyKeys(state, O, GetOwnPropertyKeysType::Symbol);
+}
+
+static Value builtinObjectIsExtensible(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return Value(Value::False);
+    }
+    // Return the Boolean value of the [[Extensible]] internal property of O.
+    return Value(argv[0].asObject()->isExtensible(state));
+}
+
+static Value builtinObjectIsFrozen(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return Value(Value::True);
+    }
+
+    bool result = Object::testIntegrityLevel(state, argv[0].asObject(), false);
+    return Value(result);
+}
+
+static Value builtinObjectIsSealed(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return Value(Value::True);
+    }
+
+    bool result = Object::testIntegrityLevel(state, argv[0].asObject(), true);
+    return Value(result);
+}
+
+static Value builtinObjectSeal(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!argv[0].isObject()) {
+        return argv[0];
+    }
+    Object* O = argv[0].asObject();
+
+    // Let status be ? SetIntegrityLevel(O, sealed).
+    // If status is false, throw a TypeError exception.
+    if (!Object::setIntegrityLevel(state, O, true)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().seal.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+    }
+
+    // Return O.
+    return O;
+}
+
+static Value builtinObjectAssign(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Object.assign ( target, ...sources )
+    // Let to be ? ToObject(target).
+    Object* to = argv[0].toObject(state);
+    // If only one argument was passed, return to.
+    if (argc == 1) {
+        return to;
+    }
+    // Let sources be the List of argument values starting with the second argument.
+    // For each element nextSource of sources, in ascending index order, do
+    for (size_t i = 1; i < argc; i++) {
+        Value nextSource = argv[i];
+        // If nextSource is undefined or null, let keys be a new empty List.
+        Object::OwnPropertyKeyVector keys;
+        Object* from = nullptr;
+        if (!nextSource.isUndefinedOrNull()) {
+            // Let from be ! ToObject(nextSource).
+            from = nextSource.toObject(state);
+            // Let keys be ? from.[[OwnPropertyKeys]]().
+            keys = from->ownPropertyKeys(state);
+        }
+
+        // For each element nextKey of keys in List order, do
+        for (size_t i = 0; i < keys.size(); i++) {
+            Value nextKey = keys[i];
+            // Let desc be ? from.[[GetOwnProperty]](nextKey).
+            auto desc = from->getOwnProperty(state, ObjectPropertyName(state, nextKey));
+            // If desc is not undefined and desc.[[Enumerable]] is true, then
+            if (desc.hasValue() && desc.isEnumerable()) {
+                // Let propValue be ? Get(from, nextKey).
+                Value propValue;
+                if (from->isProxyObject()) {
+                    propValue = from->get(state, ObjectPropertyName(state, Value(nextKey))).value(state, from);
+                } else {
+                    propValue = desc.value(state, from);
+                }
+                // Perform ? Set(to, nextKey, propValue, true).
+                to->setThrowsException(state, ObjectPropertyName(state, nextKey), propValue, to);
+            }
+        }
+    }
+    return to;
+}
+
+static Value builtinObjectIs(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // 19.1.2.10 Object.is ( value1, value2 )
+
+    // Return SameValue(value1, value2).
+    return Value(argv[0].equalsToByTheSameValueAlgorithm(state, argv[1]));
+}
+
+static Value builtinObjectKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // 19.1.2.16 Object.keys ( O )
+
+    // Let obj be ? ToObject(O).
+    Object* obj = argv[0].toObject(state);
+    // Let nameList be ? EnumerableOwnProperties(obj, "key").
+    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::Key);
+    // Return CreateArrayFromList(nameList).
+    return Object::createArrayFromList(state, nameList.size(), nameList.data());
+}
+
+static Value builtinObjectValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // 19.1.2.21 Object.values ( O )
+
+    // Let obj be ? ToObject(O).
+    Object* obj = argv[0].toObject(state);
+    // Let nameList be ? EnumerableOwnProperties(obj, "value").
+    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::Value);
+    // Return CreateArrayFromList(nameList).
+    return Object::createArrayFromList(state, nameList.size(), nameList.data());
+}
+
+static Value builtinObjectEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // 19.1.2.5 Object.entries ( O )
+
+    // Let obj be ? ToObject(O).
+    Object* obj = argv[0].toObject(state);
+    // Let nameList be ? EnumerableOwnProperties(obj, "key+value").
+    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::KeyAndValue);
+    // Return CreateArrayFromList(nameList).
+    return Object::createArrayFromList(state, nameList.size(), nameList.data());
+}
+
+void GlobalObject::installObject(ExecutionState& state)
+{
+    const StaticStrings& strings = state.context()->staticStrings();
+
+    m_object = new NativeFunctionObject(state, NativeFunctionInfo(strings.Object, builtinObjectConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_object->setGlobalIntrinsicObject(state);
+    m_object->setFunctionPrototype(state, m_objectPrototype);
+
+    // $19.1.2.2 Object.create (O [,Properties])
+    m_objectCreate = new NativeFunctionObject(state, NativeFunctionInfo(strings.create, builtinObjectCreate, 2, NativeFunctionInfo::Strict));
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.create),
+                                ObjectPropertyDescriptor(m_objectCreate,
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    // 19.1.2.3 Object.defineProperties ( O, Properties )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.defineProperties),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.defineProperties, builtinObjectDefineProperties, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.4 Object.defineProperty ( O, P, Attributes )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.defineProperty),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.defineProperty, builtinObjectDefineProperty, 3, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.5 Object.freeze ( O )
+    m_objectFreeze = new NativeFunctionObject(state, NativeFunctionInfo(strings.freeze, builtinObjectFreeze, 1, NativeFunctionInfo::Strict));
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.freeze),
+                                ObjectPropertyDescriptor(m_objectFreeze,
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // 19.1.2.7 Object.fromEntries ( iterable )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.fromEntries),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.fromEntries, builtinObjectFromEntries, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyDescriptor),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyDescriptor, builtinObjectGetOwnPropertyDescriptor, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.7 Object.getOwnPropertyNames ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyNames),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyNames, builtinObjectGetOwnPropertyNames, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertySymbols),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertySymbols, builtinObjectGetOwnPropertySymbols, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyDescriptors),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyDescriptors, builtinObjectGetOwnPropertyDescriptors, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.9 Object.getPrototypeOf ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getPrototypeOf),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getPrototypeOf, builtinObjectGetPrototypeOf, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.11 Object.isExtensible ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isExtensible),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isExtensible, builtinObjectIsExtensible, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.12 Object.isFrozen ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isFrozen),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isFrozen, builtinObjectIsFrozen, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.13 Object.isSealed ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isSealed),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isSealed, builtinObjectIsSealed, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.14 Object.keys ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.keys),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.keys, builtinObjectKeys, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.15 Object.preventExtensions ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.preventExtensions),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.preventExtensions, builtinObjectPreventExtensions, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.17 Object.seal ( O )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.seal),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.seal, builtinObjectSeal, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 19.1.2.20 Object.setPrototypeOf ( O, proto )
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.setPrototypeOf),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.setPrototypeOf, builtinObjectSetPrototypeOf, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    // ES6+ Object.assign
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.assign),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.assign, builtinObjectAssign, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // ES6+ Object.is
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.is),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.is, builtinObjectIs, 2, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.constructor),
+                                         ObjectPropertyDescriptor(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.toString),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.toString, builtinObjectToString, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.valueOf),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.valueOf, builtinObjectValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // ES2017 Object.values
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.values),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.values, builtinObjectValues, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // ES2017 Object.entries
+    m_object->defineOwnProperty(state, ObjectPropertyName(strings.entries),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.entries, builtinObjectEntries, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.1.3.2 Object.prototype.hasOwnProperty(V)
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.hasOwnProperty),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.hasOwnProperty, builtinObjectHasOwnProperty, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.1.3.4 Object.prototype.isPrototypeOf(V)
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.isPrototypeOf),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isPrototypeOf, builtinObjectIsPrototypeOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.1.3.4 Object.prototype.propertyIsEnumerable(V)
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.propertyIsEnumerable),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.propertyIsEnumerable, builtinObjectPropertyIsEnumerable, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.1.3.5 Object.prototype.toLocaleString()
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.toLocaleString),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.toLocaleString, builtinObjectToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $19.1.3.4 Object.prototype.propertyIsEnumerable(V)
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().propertyIsEnumerable),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().propertyIsEnumerable, builtinObjectPropertyIsEnumerable, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    JSGetterSetter gs(
+        new NativeFunctionObject(state, NativeFunctionInfo(strings.get__proto__, builtinObject__proto__Getter, 0, NativeFunctionInfo::Strict)),
+        new NativeFunctionObject(state, NativeFunctionInfo(strings.set__proto__, builtinObject__proto__Setter, 1, NativeFunctionInfo::Strict)));
+    ObjectPropertyDescriptor __proto__desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__proto__), __proto__desc);
+    defineOwnProperty(state, ObjectPropertyName(strings.Object),
+                      ObjectPropertyDescriptor(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_objectPrototypeToString = new NativeFunctionObject(state, NativeFunctionInfo(strings.toString, builtinObjectToString, 0, NativeFunctionInfo::Strict));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinPromise.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinPromise.cpp
new file mode 100644 (file)
index 0000000..4949c79
--- /dev/null
@@ -0,0 +1,812 @@
+/*
+ * Copyright (c) 2017-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/PromiseObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/JobQueue.h"
+#include "runtime/SandBox.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/ExtendedNativeFunctionObject.h"
+
+namespace Escargot {
+
+// $25.4.3 Promise(executor)
+static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise constructor should be called with new Promise()");
+    }
+
+    Value executor = argv[0];
+    if (!executor.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise executor is not a function object");
+    }
+
+    // Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->promisePrototype();
+    });
+    PromiseObject* promise = new PromiseObject(state, proto);
+
+    PromiseReaction::Capability capability = promise->createResolvingFunctions(state);
+
+    // PromiseHook for Promise initialization case
+    if (UNLIKELY(state.context()->vmInstance()->isPromiseHookRegistered())) {
+        // Note) To pass parent promise, we allocate the second argument (argv[1]) for the parent promise
+        // otherwise, the second argument would be ignored
+        state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Init, promise, (argc > 1) ? argv[1] : Value());
+    }
+
+    SandBox sb(state.context());
+    auto res = sb.run([&]() -> Value {
+        Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction };
+        Object::call(state, executor, Value(), 2, arguments);
+        return Value();
+    });
+    if (!res.error.isEmpty()) {
+        Value arguments[] = { res.error };
+        Object::call(state, capability.m_rejectFunction, Value(), 1, arguments);
+    }
+
+    return promise;
+}
+
+// https://tc39.es/ecma262/#sec-getpromiseresolve
+static Value getPromiseResolve(ExecutionState& state, Object* promiseConstructor)
+{
+    // Assert: IsConstructor(promiseConstructor) is true.
+    // Let promiseResolve be ? Get(promiseConstructor, "resolve").
+    auto promiseResolve = promiseConstructor->get(state, state.context()->staticStrings().resolve).value(state, promiseConstructor);
+    // If IsCallable(promiseResolve) is false, throw a TypeError exception.
+    if (!promiseResolve.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Promise resolve is not callable");
+    }
+    // Return promiseResolve.
+    return promiseResolve;
+}
+
+static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://tc39.es/ecma262/#sec-performpromiseall
+    auto strings = &state.context()->staticStrings();
+
+    // Let C be the this value.
+    // If Type(C) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->all.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    Object* C = thisValue.asObject();
+    // Let promiseCapability be NewPromiseCapability(C).
+    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
+    // Let promiseResolve be GetPromiseResolve(C).
+    Value promiseResolve;
+    try {
+        promiseResolve = getPromiseResolve(state, C);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let iteratorRecord be GetIterator(iterable).
+    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+    IteratorRecord* iteratorRecord;
+    try {
+        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
+    Value result;
+    try {
+        // Let values be a new empty List.
+        ValueVector* values = new ValueVector();
+        // Let remainingElementsCount be a new Record { [[value]]: 1 }.
+        size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
+
+        // Let index be 0.
+        int64_t index = 0;
+
+        // Repeat
+        while (true) {
+            // Let next be IteratorStep(iteratorRecord).
+            Optional<Object*> next;
+            try {
+                next = IteratorObject::iteratorStep(state, iteratorRecord);
+            } catch (const Value& e) {
+                // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
+                iteratorRecord->m_done = true;
+                // ReturnIfAbrupt(next).
+                state.throwException(e);
+            }
+            // If next is false,
+            if (!next.hasValue()) {
+                // set iteratorRecord.[[done]] to true.
+                iteratorRecord->m_done = true;
+                // Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
+                *remainingElementsCount = *remainingElementsCount - 1;
+                // If remainingElementsCount.[[value]] is 0,
+                if (*remainingElementsCount == 0) {
+                    // Let valuesArray be CreateArrayFromList(values).
+                    // Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
+                    Value argv = Object::createArrayFromList(state, *values);
+                    Value resolveResult = Object::call(state, promiseCapability.m_resolveFunction, Value(), 1, &argv);
+                }
+                // Return resultCapability.[[Promise]].
+                result = promiseCapability.m_promise;
+                break;
+            }
+            // Let nextValue be IteratorValue(next).
+            Value nextValue;
+            try {
+                nextValue = IteratorObject::iteratorValue(state, next.value());
+            } catch (const Value& e) {
+                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
+                iteratorRecord->m_done = true;
+                // ReturnIfAbrupt(nextValue).
+                state.throwException(e);
+            }
+            // Append undefined to values.
+            values->pushBack(Value());
+            // Let nextPromise be Invoke(constructor, "resolve", « nextValue »).
+            Value nextPromise = Object::call(state, promiseResolve, C, 1, &nextValue);
+
+            // Let resolveElement be a new built-in function object as defined in Promise.all Resolve Element Functions.
+            ExtendedNativeFunctionObject* resolveElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllResolveElementFunction, 1, NativeFunctionInfo::Strict));
+
+            // Set the [[AlreadyCalled]] internal slot of resolveElement to a new Record {[[value]]: false }.
+            // Set the [[Index]] internal slot of resolveElement to index.
+            // Set the [[Values]] internal slot of resolveElement to values.
+            // Set the [[Capabilities]] internal slot of resolveElement to resultCapability.
+            // Set the [[RemainingElements]] internal slot of resolveElement to remainingElementsCount.
+            bool* alreadyCalled = new (PointerFreeGC) bool(false);
+
+            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
+            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
+            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
+            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, promiseCapability.m_resolveFunction);
+            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, promiseCapability.m_rejectFunction);
+            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
+
+            // Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] + 1.
+            *remainingElementsCount = *remainingElementsCount + 1;
+            // Perform ? Invoke(nextPromise, "then", « resolveElement, resultCapability.[[Reject]] »).
+            Object* nextPromiseObject = nextPromise.toObject(state);
+            Value argv[] = { Value(resolveElement), Value(promiseCapability.m_rejectFunction) };
+            Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv);
+            // Increase index by 1.
+            index++;
+        }
+    } catch (const Value& v) {
+        Value exceptionValue = v;
+        // If result is an abrupt completion,
+        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
+        // IfAbruptRejectPromise(result, promiseCapability).
+        try {
+            if (!iteratorRecord->m_done) {
+                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+            }
+        } catch (const Value& v) {
+            exceptionValue = v;
+        }
+
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Return Completion(result).
+    return result;
+}
+
+static Value builtinPromiseRace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://tc39.es/ecma262/#sec-performpromiserace
+    auto strings = &state.context()->staticStrings();
+    // Let C be the this value.
+    // If Type(C) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->race.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    Object* C = thisValue.asObject();
+
+    // Let promiseCapability be NewPromiseCapability(C).
+    // ReturnIfAbrupt(promiseCapability).
+    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
+    // Let promiseResolve be GetPromiseResolve(C).
+    Value promiseResolve;
+    try {
+        promiseResolve = getPromiseResolve(state, C);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let iteratorRecord be GetIterator(iterable).
+    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+    IteratorRecord* iteratorRecord;
+    try {
+        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Let rejectResult be Call(capability.[[Reject]], undefined, «value.[[value]]»).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
+    Value result;
+    try {
+        // Repeat
+        while (true) {
+            // Let next be IteratorStep(iteratorRecord).
+            Optional<Object*> next;
+            try {
+                next = IteratorObject::iteratorStep(state, iteratorRecord);
+            } catch (const Value& e) {
+                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
+                // ReturnIfAbrupt(next).
+                iteratorRecord->m_done = true;
+                state.throwException(e);
+            }
+            // If next is false, then
+            if (!next.hasValue()) {
+                // Set iteratorRecord.[[done]] to true.
+                iteratorRecord->m_done = true;
+                // Return resultCapability.[[Promise]].
+                result = promiseCapability.m_promise;
+                break;
+            }
+
+            // Let nextValue be IteratorValue(next).
+            Value nextValue;
+            try {
+                nextValue = IteratorObject::iteratorValue(state, next.value());
+            } catch (const Value& e) {
+                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
+                iteratorRecord->m_done = true;
+                // ReturnIfAbrupt(next).
+                state.throwException(e);
+            }
+
+            // Let nextPromise be Invoke(C, "resolve", «nextValue»).
+            Value nextPromise = Object::call(state, promiseResolve, C, 1, &nextValue);
+            // Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).
+            Object* nextPromiseObject = nextPromise.toObject(state);
+            Value argv[] = { Value(promiseCapability.m_resolveFunction), Value(promiseCapability.m_rejectFunction) };
+            Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv);
+        }
+    } catch (const Value& e) {
+        Value exceptionValue = e;
+        // If result is an abrupt completion, then
+        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
+        // IfAbruptRejectPromise(result, promiseCapability).
+        try {
+            if (!iteratorRecord->m_done) {
+                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+            }
+        } catch (const Value& v) {
+            exceptionValue = v;
+        }
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Return Completion(result).
+    return result;
+}
+
+static Value builtinPromiseReject(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Object* thisObject = thisValue.toObject(state);
+    PromiseReaction::Capability capability = PromiseObject::newPromiseCapability(state, thisObject);
+
+    Value arguments[] = { argv[0] };
+    Object::call(state, capability.m_rejectFunction, Value(), 1, arguments);
+    return capability.m_promise;
+}
+
+// http://www.ecma-international.org/ecma-262/10.0/#sec-promise.resolve
+static Value builtinPromiseResolve(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let C be the this value.
+    const Value& C = thisValue;
+    // If Type(C) is not Object, throw a TypeError exception.
+    if (!C.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Promise.string(), false, state.context()->staticStrings().resolve.string(), "%s: PromiseResolve called on non-object");
+    }
+    // Return ? PromiseResolve(C, x).
+    return PromiseObject::promiseResolve(state, C.asObject(), argv[0]);
+}
+
+static Value builtinPromiseCatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Object* thisObject = thisValue.toObject(state);
+    Value onRejected = argv[0];
+    Value then = thisObject->get(state, strings->then).value(state, thisObject);
+    Value arguments[] = { Value(), onRejected };
+    return Object::call(state, then, thisObject, 2, arguments);
+}
+
+
+static Value builtinPromiseFinally(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-promise.prototype.finally
+    auto strings = &state.context()->staticStrings();
+
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->finally.string(), "%s: not a Promise object");
+    }
+
+    Object* thisObject = thisValue.asObject();
+    Value C = thisObject->speciesConstructor(state, state.context()->globalObject()->promise());
+
+    Value onFinally = argv[0];
+    Value arguments[] = { onFinally, onFinally };
+
+    if (onFinally.isCallable()) {
+        ExtendedNativeFunctionObject* thenFinally = new ExtendedNativeFunctionObjectImpl<2>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseThenFinally, 1, NativeFunctionInfo::Strict));
+        thenFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Constructor, C);
+        thenFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::OnFinally, onFinally);
+
+        ExtendedNativeFunctionObject* catchFinally = new ExtendedNativeFunctionObjectImpl<2>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseCatchFinally, 1, NativeFunctionInfo::Strict));
+        catchFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Constructor, C);
+        catchFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::OnFinally, onFinally);
+
+        arguments[0] = thenFinally;
+        arguments[1] = catchFinally;
+    }
+
+    Value then = thisObject->get(state, strings->then).value(state, thisObject);
+    return Object::call(state, then, thisObject, 2, arguments);
+}
+
+static Value builtinPromiseThen(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    if (!thisValue.isObject() || !thisValue.asObject()->isPromiseObject())
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->then.string(), "%s: not a Promise object");
+    Value C = thisValue.asObject()->speciesConstructor(state, state.context()->globalObject()->promise());
+    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C.asObject(), thisValue.asObject()->asPromiseObject());
+    return thisValue.asObject()->asPromiseObject()->then(state, argv[0], argv[1], promiseCapability).value();
+}
+
+// https://tc39.es/ecma262/#sec-performpromiseallsettled
+static Value performPromiseAllSettled(ExecutionState& state, IteratorRecord* iteratorRecord, Object* constructor, PromiseReaction::Capability& resultCapability, Value promiseResolve)
+{
+    // Assert: ! IsConstructor(constructor) is true.
+    // Assert: resultCapability is a PromiseCapability Record.
+    // Let values be a new empty List.
+    ValueVector* values = new ValueVector();
+    // Let remainingElementsCount be a new Record { [[Value]]: 1 }.
+    size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
+    // Let index be 0.
+    size_t index = 0;
+
+    // Repeat,
+    while (true) {
+        // Let next be IteratorStep(iteratorRecord).
+        Optional<Object*> next;
+        try {
+            next = IteratorObject::iteratorStep(state, iteratorRecord);
+        } catch (const Value& e) {
+            // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
+            iteratorRecord->m_done = true;
+            // ReturnIfAbrupt(next).
+            state.throwException(e);
+        }
+
+        // If next is false, then
+        if (!next.hasValue()) {
+            // Set iteratorRecord.[[Done]] to true.
+            iteratorRecord->m_done = true;
+            // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
+            *remainingElementsCount = *remainingElementsCount - 1;
+            // If remainingElementsCount.[[Value]] is 0, then
+            if (*remainingElementsCount == 0) {
+                // Let valuesArray be ! CreateArrayFromList(values).
+                Value valuesArray = ArrayObject::createArrayFromList(state, *values);
+                // Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
+                Object::call(state, resultCapability.m_resolveFunction, Value(), 1, &valuesArray);
+            }
+            // Return resultCapability.[[Promise]].
+            return resultCapability.m_promise;
+        }
+
+        // Let nextValue be IteratorValue(next).
+        Value nextValue;
+        try {
+            nextValue = IteratorObject::iteratorValue(state, next.value());
+        } catch (const Value& e) {
+            // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
+            iteratorRecord->m_done = true;
+            // ReturnIfAbrupt(nextValue).
+            state.throwException(e);
+        }
+
+        // Append undefined to values.
+        values->pushBack(Value());
+        // Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
+        Value nextValueArgv = nextValue;
+        Value nextPromise = Object::call(state, promiseResolve, constructor, 1, &nextValueArgv);
+        // Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
+        // Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
+        // Let alreadyCalled be the Record { [[Value]]: false }.
+        bool* alreadyCalled = new (PointerFreeGC) bool(false);
+        // Set resolveElement.[[AlreadyCalled]] to alreadyCalled.
+        // Set resolveElement.[[Index]] to index.
+        // Set resolveElement.[[Values]] to values.
+        // Set resolveElement.[[Capability]] to resultCapability.
+        // Set resolveElement.[[RemainingElements]] to remainingElementsCount.
+        auto resolveElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllSettledResolveElementFunction, 1, NativeFunctionInfo::Strict));
+        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
+        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
+        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
+        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
+        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
+        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
+
+        // Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions.
+        // Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
+        // Set rejectElement.[[AlreadyCalled]] to alreadyCalled.
+        // Set rejectElement.[[Index]] to index.
+        // Set rejectElement.[[Values]] to values.
+        // Set rejectElement.[[Capability]] to resultCapability.
+        // Set rejectElement.[[RemainingElements]] to remainingElementsCount.
+        auto rejectElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllSettledRejectElementFunction, 1, NativeFunctionInfo::Strict));
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
+
+        // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
+        *remainingElementsCount = *remainingElementsCount + 1;
+        // Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »).
+        Value argv[2] = { resolveElement, rejectElement };
+        Object::call(state, Object::getMethod(state, nextPromise, state.context()->staticStrings().then), nextPromise, 2, argv);
+        // Set index to index + 1.
+        index++;
+    }
+
+    return Value();
+}
+
+// https://tc39.es/ecma262/#sec-promise.allsettled
+static Value builtinPromiseAllSettled(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let C be the this value.
+    // If Type(C) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "this value of allSettled is not Object");
+    }
+    Object* C = thisValue.asObject();
+    // Let promiseCapability be ? NewPromiseCapability(C).
+    auto promiseCapability = PromiseObject::newPromiseCapability(state, C);
+    // Let promiseResolve be GetPromiseResolve(C).
+    Value promiseResolve;
+    try {
+        promiseResolve = getPromiseResolve(state, C);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let iteratorRecord be GetIterator(iterable).
+    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+    IteratorRecord* iteratorRecord;
+    try {
+        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    Value result;
+    // Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability).
+    try {
+        result = performPromiseAllSettled(state, iteratorRecord, C, promiseCapability, promiseResolve);
+    } catch (const Value& v) {
+        Value exceptionValue = v;
+        // If result is an abrupt completion,
+        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
+        if (!iteratorRecord->m_done) {
+            try {
+                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+            } catch (const Value& v) {
+                // IfAbruptRejectPromise(result, promiseCapability).
+                // If value is an abrupt completion,
+                // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+                Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
+                // Return capability.[[Promise]].
+                return promiseCapability.m_promise;
+            }
+        } else {
+            // IfAbruptRejectPromise(result, promiseCapability).
+            // If value is an abrupt completion,
+            // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+            Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
+            // Return capability.[[Promise]].
+            return promiseCapability.m_promise;
+        }
+    }
+    // Return Completion(result).
+    return result;
+}
+
+// https://tc39.es/ecma262/#sec-performpromiseany
+static Value performPromiseAny(ExecutionState& state, IteratorRecord* iteratorRecord, Object* constructor, const PromiseReaction::Capability& resultCapability, const Value& promiseResolve)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    // Assert: ! IsConstructor(constructor) is true.
+    // Assert: ! IsCallable(promiseResolve) is true.
+    // Let errors be a new empty List.
+    ValueVector* errors = new ValueVector();
+    // Let remainingElementsCount be the Record { [[Value]]: 1 }.
+    size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
+    // Let index be 0.
+    int64_t index = 0;
+    // Repeat,
+    while (true) {
+        // Let next be IteratorStep(iteratorRecord).
+        // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
+        // ReturnIfAbrupt(next).
+        Optional<Object*> next;
+        try {
+            next = IteratorObject::iteratorStep(state, iteratorRecord);
+        } catch (const Value& v) {
+            iteratorRecord->m_done = true;
+            throw v;
+        }
+
+        // If next is false, then
+        if (!next.hasValue()) {
+            // Set iteratorRecord.[[Done]] to true.
+            iteratorRecord->m_done = true;
+            // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
+            *remainingElementsCount = *remainingElementsCount - 1;
+            // If remainingElementsCount.[[Value]] is 0, then
+            if (*remainingElementsCount == 0) {
+                // Let error be a newly created AggregateError object.
+                ErrorObject* error = ErrorObject::createBuiltinError(state, ErrorObject::AggregateError, "Got AggregateError on processing Promise.any");
+                // Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
+                error->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, String::fromASCII("errors")),
+                                                        ObjectPropertyDescriptor(Object::createArrayFromList(state, *errors),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
+                // Return ThrowCompletion(error).
+                throw Value(error);
+            }
+            // Return resultCapability.[[Promise]].
+            return resultCapability.m_promise;
+        }
+
+        // Let nextValue be IteratorValue(next).
+        Value nextValue;
+        try {
+            nextValue = IteratorObject::iteratorValue(state, next.value());
+        } catch (const Value& v) {
+            // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
+            iteratorRecord->m_done = true;
+            // ReturnIfAbrupt(nextValue).
+            throw v;
+        }
+        // Append undefined to errors.
+        errors->pushBack(Value());
+        // Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
+        Value argv = nextValue;
+        Value nextPromise = Object::call(state, promiseResolve, constructor, 1, &argv);
+        // Let steps be the algorithm steps defined in Promise.any Reject Element Functions.
+        // Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
+        ExtendedNativeFunctionObject* rejectElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAnyRejectElementFunction, 1, NativeFunctionInfo::Strict));
+        // Set rejectElement.[[AlreadyCalled]] to false.
+        // Set rejectElement.[[Index]] to index.
+        // Set rejectElement.[[Errors]] to errors.
+        // Set rejectElement.[[Capability]] to resultCapability.
+        // Set rejectElement.[[RemainingElements]] to remainingElementsCount.
+        bool* alreadyCalled = new (PointerFreeGC) bool(false);
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Errors, errors);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
+        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
+        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
+        // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
+        *remainingElementsCount = *remainingElementsCount + 1;
+
+        // Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »).
+        Object* nextPromiseObject = nextPromise.toObject(state);
+        Value argv2[] = { Value(resultCapability.m_resolveFunction), Value(rejectElement) };
+        Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv2);
+        // Set index to index + 1.
+        index++;
+    }
+    ASSERT_NOT_REACHED();
+}
+
+// https://tc39.es/ecma262/#sec-promise.any
+static Value builtinPromiseAny(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    // Let C be the this value.
+    // If Type(C) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->all.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    Object* C = thisValue.asObject();
+
+    // Let promiseCapability be NewPromiseCapability(C).
+    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
+    // Let promiseResolve be GetPromiseResolve(C).
+    // IfAbruptRejectPromise(promiseResolve, promiseCapability).
+    Value promiseResolve;
+    try {
+        promiseResolve = getPromiseResolve(state, C);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let iteratorRecord be GetIterator(iterable).
+    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+    const Value& iterable = argv[0];
+    IteratorRecord* iteratorRecord = nullptr;
+    try {
+        iteratorRecord = IteratorObject::getIterator(state, iterable);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If value is an abrupt completion,
+        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        // Return capability.[[Promise]].
+        return promiseCapability.m_promise;
+    }
+
+    // Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve).
+    Value result;
+    try {
+        result = performPromiseAny(state, iteratorRecord, C, promiseCapability, promiseResolve);
+    } catch (const Value& v) {
+        Value thrownValue = v;
+        // If result is an abrupt completion, then
+        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
+        try {
+            if (!iteratorRecord->m_done) {
+                IteratorObject::iteratorClose(state, iteratorRecord, thrownValue, true);
+            }
+        } catch (const Value& v) {
+            thrownValue = v;
+        }
+        // IfAbruptRejectPromise(result, promiseCapability).
+        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
+        return promiseCapability.m_promise;
+    }
+    // Return Completion(result).
+    return result;
+}
+
+void GlobalObject::installPromise(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_promise = new NativeFunctionObject(state, NativeFunctionInfo(strings->Promise, builtinPromiseConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_promise->setGlobalIntrinsicObject(state);
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_promise->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    m_promisePrototype = new Object(state);
+    m_promisePrototype->setGlobalIntrinsicObject(state, true);
+
+    m_promisePrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().Promise.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $25.4.4.1 Promise.all(iterable);
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->all),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->all, builtinPromiseAll, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.4.3 Promise.race(iterable)
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->race),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->race, builtinPromiseRace, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.4.4 Promise.reject(r)
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reject),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reject, builtinPromiseReject, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.4.5 Promise.resolve(r)
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->resolve),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolve, builtinPromiseResolve, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.5.1 Promise.prototype.catch(onRejected)
+    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->stringCatch),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->stringCatch, builtinPromiseCatch, 1, NativeFunctionInfo::Strict)),
+                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
+    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->then),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->then, builtinPromiseThen, 2, NativeFunctionInfo::Strict)),
+                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.6.5.3 Promise.prototype.finally ( onFinally )
+    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->finally),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->finally, builtinPromiseFinally, 1, NativeFunctionInfo::Strict)),
+                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $25.4.5.4 Promise.prototype [ @@toStringTag ]
+    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().Promise.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_promise->setFunctionPrototype(state, m_promisePrototype);
+
+    // Promise.allSettled ( iterable )
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->allSettled),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->allSettled, builtinPromiseAllSettled, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // Promise.any ( iterable )
+    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->any),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->any, builtinPromiseAny, 1, NativeFunctionInfo::Strict)),
+                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    defineOwnProperty(state, ObjectPropertyName(strings->Promise),
+                      ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinProxy.cpp
new file mode 100644 (file)
index 0000000..c3f8ace
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/ProxyObject.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ExtendedNativeFunctionObject.h"
+
+namespace Escargot {
+
+// $26.2.1 The Proxy Constructor
+static Value builtinProxyConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Proxy.string(), false, String::emptyString, "%s: calling a builtin Proxy constructor without new is forbidden");
+        return Value();
+    }
+
+    Value target = argv[0];
+    Value handler = argv[1];
+
+    return ProxyObject::createProxy(state, target, handler);
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-proxy-revocation-functions
+static Value builtinProxyRevoke(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+
+    ExtendedNativeFunctionObject* revoke = state.resolveCallee()->asExtendedNativeFunctionObject();
+    ASSERT(revoke);
+
+    // 1. Let p be the value of F’s [[RevocableProxy]] internal slot.
+    Value p = revoke->internalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy);
+
+    // 2. If p is null, return undefined.
+    if (p.isNull()) {
+        return Value();
+    }
+
+    ProxyObject* proxy = p.asObject()->asProxyObject();
+
+    // 3. Set the value of F’s [[RevocableProxy]] internal slot to null.
+    revoke->setInternalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy, Value(Value::Null));
+
+    // 5. Set the [[ProxyTarget]] internal slot of p to null.
+    proxy->setTarget(nullptr);
+
+    // 6. Set the [[ProxyHandler]] internal slot of p to null.
+    proxy->setHandler(nullptr);
+
+    // 6. Return undefined.
+    return Value();
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-proxy.revocable
+static Value builtinProxyRevocable(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+
+    Value target = argv[0];
+    Value handler = argv[1];
+
+    // 1. Let p be ProxyCreate(target, handler).
+    Value proxy = ProxyObject::createProxy(state, target, handler);
+
+    // 3. Let revoker be a new built-in function object as defined in 26.2.2.1.1.
+    // 4. Set the [[RevocableProxy]] internal slot of revoker to p.
+    ExtendedNativeFunctionObject* revoker = new ExtendedNativeFunctionObjectImpl<1>(state, NativeFunctionInfo(AtomicString(), builtinProxyRevoke, 0, NativeFunctionInfo::Strict));
+    revoker->setInternalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy, proxy);
+
+    // 5. Let result be ObjectCreate(%ObjectPrototype%).
+    Object* result = new Object(state);
+
+    // 6. Perform CreateDataProperty(result, "proxy", p).
+    result->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->proxy),
+                                             ObjectPropertyDescriptor(proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 7. Perform CreateDataProperty(result, "revoke", revoker).
+    result->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->revoke),
+                                             ObjectPropertyDescriptor(revoker, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // 8. Return result.
+    return result;
+}
+
+void GlobalObject::installProxy(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_proxy = new NativeFunctionObject(state, NativeFunctionInfo(strings->Proxy, builtinProxyConstructor, 2), NativeFunctionObject::__ForBuiltinProxyConstructor__);
+    m_proxy->setGlobalIntrinsicObject(state);
+
+    m_proxy->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->revocable), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->revocable, builtinProxyRevocable, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(strings->Proxy),
+                      ObjectPropertyDescriptor(m_proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinReflect.cpp
new file mode 100644 (file)
index 0000000..ee8f6ef
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/Object.h"
+#include "runtime/ProxyObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "interpreter/ByteCodeInterpreter.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/VMInstance.h"
+
+namespace Escargot {
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.apply
+static Value builtinReflectApply(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+    Value thisArgument = argv[1];
+    Value argList = argv[2];
+
+    // 1. If IsCallable(target) is false, throw a TypeError exception.
+    if (!target.isObject() || !target.asObject()->isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: calling a not-callable target in apply function is forbidden");
+    }
+
+    // 2. Let args be CreateListFromArrayLike(argumentsList).
+    auto args = Object::createListFromArrayLike(state, argList);
+
+    // 5. Return Call(target, thisArgument, args).
+    return Object::call(state, target, thisArgument, args.size(), args.data());
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.construct
+static Value builtinReflectConstruct(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+    Value argList = argv[1];
+    Value newTargetArg = argc > 2 ? argv[2] : target;
+
+    // 1. If IsConstructor(target) is false, throw a TypeError exception.
+    if (!target.isConstructor()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.construct should has a construct method");
+    }
+
+    // 2. If newTarget is not present, let newTarget be target.
+    // 3. Else, if IsConstructor(newTarget) is false, throw a TypeError exception.
+    if (!newTargetArg.isConstructor()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The new target of Reflect.construct should be a constructor");
+    }
+
+    // 4. Let args be CreateListFromArrayLike(argumentsList).
+    auto args = Object::createListFromArrayLike(state, argList);
+    // 6. Return Construct(target, args, newTarget).
+    return Object::construct(state, target, args.size(), args.data(), newTargetArg.asObject());
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.defineproperty
+static Value builtinReflectDefineProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.defineProperty should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 3. Let desc be ToPropertyDescriptor(attributes).
+    ObjectPropertyDescriptor desc(state, argv[2].asObject());
+
+    // 6. Return target.[[DefineOwnProperty]](key, desc).
+    return Value(target.asObject()->defineOwnProperty(state, ObjectPropertyName(state, key), desc));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.deleteproperty
+static Value builtinReflectDeleteProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.deleteProperty should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 4. Return target.[[Delete]](key).
+    return Value(target.asObject()->deleteOwnProperty(state, ObjectPropertyName(state, key)));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.get
+static Value builtinReflectGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.get should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 4. If receiver is not present, then
+    // 4.a. Let receiver be target.
+    Value receiver = argc > 2 ? argv[2] : target;
+
+    // 5. Return target.[[Get]](key, receiver).
+    return target.asObject()->get(state, ObjectPropertyName(state, key)).value(state, receiver);
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.getownpropertydescriptor
+static Value builtinReflectGetOwnPropertyDescriptor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.getOwnPropertyDescriptor should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 4. Let desc be target.[[GetOwnProperty]](key).
+    ObjectGetResult desc = target.asObject()->getOwnProperty(state, ObjectPropertyName(state, key));
+
+    // 6. Return FromPropertyDescriptor(desc).
+    return desc.fromPropertyDescriptor(state, target.asObject());
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.getprototypeof
+static Value builtinReflectGetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.getPrototypeOf should be an Object");
+    }
+
+    // 2. Return target.[[GetPrototypeOf]]().
+    return target.asObject()->getPrototype(state);
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.has
+static Value builtinReflectHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.has should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 4. Return target.[[HasProperty]](key).
+    return Value(target.asObject()->hasProperty(state, ObjectPropertyName(state, key)));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.isextensible
+static Value builtinReflectIsExtensible(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.isExtensible should be an Object");
+    }
+
+    // 2. Return target.[[IsExtensible]]().
+    return Value(target.asObject()->isExtensible(state));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.preventextensions
+static Value builtinReflectPreventExtensions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.preventExtension should be an Object");
+    }
+
+    // 2. Return target.[[PreventExtensions]]().
+    return Value(target.asObject()->preventExtensions(state));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.ownkeys
+static Value builtinReflectOwnKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.preventExtension should be an Object");
+    }
+    // 2. Let keys be target.[[OwnPropertyKeys]]().
+    // 3. ReturnIfAbrupt(keys).
+    auto keys = target.asObject()->ownPropertyKeys(state);
+    // 4. Return CreateArrayFromList(keys).
+    return Object::createArrayFromList(state, keys.size(), keys.data());
+}
+
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.set
+static Value builtinReflectSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.set should be an Object");
+    }
+
+    // 2. Let key be ToPropertyKey(propertyKey).
+    Value key = argv[1].toPropertyKey(state);
+
+    // 4. If receiver is not present, then
+    // 4.a. Let receiver be target.
+    Value receiver = argc > 3 ? argv[3] : target;
+
+    // 5. Return target.[[Set]](key, V, receiver).
+    return Value(target.asObject()->set(state, ObjectPropertyName(state, key), argv[2], receiver));
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.setprototypeof
+static Value builtinReflectSetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    auto strings = &state.context()->staticStrings();
+    Value target = argv[0];
+    Value proto = argv[1];
+
+    // 1. If Type(target) is not Object, throw a TypeError exception.
+    if (!target.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.setPrototypeOf should be an Object");
+    }
+
+    // 2. If Type(proto) is not Object and proto is not null, throw a TypeError exception
+    if (!proto.isObject() && !proto.isNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The proto of Reflect.setPrototypeOf should be an Object or Null");
+    }
+
+    // 3. Return target.[[SetPrototypeOf]](proto).
+    return Value(target.asObject()->setPrototype(state, proto));
+}
+
+void GlobalObject::installReflect(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_reflect = new Object(state);
+    m_reflect->setGlobalIntrinsicObject(state);
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().apply),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().apply, builtinReflectApply, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().construct),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().construct, builtinReflectConstruct, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().defineProperty),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().defineProperty, builtinReflectDefineProperty, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().deleteProperty),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().deleteProperty, builtinReflectDeleteProperty, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinReflectGet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().getOwnPropertyDescriptor),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getOwnPropertyDescriptor, builtinReflectGetOwnPropertyDescriptor, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().getPrototypeOf),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getPrototypeOf, builtinReflectGetPrototypeOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinReflectHas, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().isExtensible),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().isExtensible, builtinReflectIsExtensible, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().preventExtensions),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().preventExtensions, builtinReflectPreventExtensions, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().ownKeys),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().ownKeys, builtinReflectOwnKeys, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinReflectSet, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().setPrototypeOf),
+                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setPrototypeOf, builtinReflectSetPrototypeOf, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                ObjectPropertyDescriptor(state.context()->staticStrings().Reflect.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(strings->Reflect),
+                      ObjectPropertyDescriptor(m_reflect, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinRegExp.cpp
new file mode 100644 (file)
index 0000000..ee14b7b
--- /dev/null
@@ -0,0 +1,927 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/RegExpObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinRegExpConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value pattern = argv[0];
+    Value flags = argv[1];
+    String* source = pattern.isUndefined() ? String::emptyString : pattern.toString(state);
+    String* option = flags.isUndefined() ? String::emptyString : flags.toString(state);
+
+    // Let patternIsRegExp be IsRegExp(pattern).
+    bool patternIsRegExp = argv[0].isObject() && argv[0].asObject()->isRegExp(state);
+
+    if (!newTarget.hasValue()) {
+        // Let newTarget be the active function object.
+        newTarget = state.resolveCallee();
+        // If patternIsRegExp is true and flags is undefined, then
+        if (patternIsRegExp && flags.isUndefined()) {
+            // Let patternConstructor be Get(pattern, "constructor").
+            Value patternConstructor = pattern.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().constructor)).value(state, pattern);
+            // If SameValue(patternConstructor, newTarget), then return pattern.
+            if (patternConstructor.isObject() && patternConstructor.asObject() == newTarget.value()) {
+                return pattern;
+            }
+        }
+    }
+
+    // If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal slot, then
+    if (pattern.isObject() && pattern.asObject()->isRegExpObject()) {
+        RegExpObject* patternRegExp = pattern.asObject()->asRegExpObject();
+        // Let P be the value of pattern’s [[OriginalSource]] internal slot.
+        source = patternRegExp->source();
+        // If flags is undefined, let F be the value of pattern’s [[OriginalFlags]] internal slot.
+        // Else, let F be flags.
+        option = flags.isUndefined() ? patternRegExp->optionString(state) : flags.toString(state);
+    } else if (patternIsRegExp) {
+        Value P = pattern.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().source)).value(state, pattern);
+        source = P.isUndefined() ? String::emptyString : P.toString(state);
+        if (flags.isUndefined()) {
+            Value F = pattern.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, pattern);
+            option = F.isUndefined() ? String::emptyString : F.toString(state);
+        }
+    }
+
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->regexpPrototype();
+    });
+    RegExpObject* regexp = new RegExpObject(state, proto, source, option);
+
+    if (newTarget != state.context()->globalObject()->regexp()) {
+        regexp->setLegacyFeaturesEnabled(false);
+    }
+
+    // TODO http://www.ecma-international.org/ecma-262/6.0/index.html#sec-escaperegexppattern
+    return regexp;
+}
+
+static Value builtinRegExpExec(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, RegExp, exec);
+    if (!thisObject->isRegExpObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().exec.string(), ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+    }
+    RegExpObject* regexp = thisObject->asRegExpObject();
+    unsigned int option = regexp->option();
+    String* str = argv[0].toString(state);
+    uint64_t lastIndex = 0;
+    if (option & (RegExpObject::Global | RegExpObject::Sticky)) {
+        lastIndex = regexp->computedLastIndex(state);
+        if (lastIndex > str->length()) {
+            regexp->setLastIndex(state, Value(0));
+            return Value(Value::Null);
+        }
+    } else {
+        // dummy get lastIndex
+        regexp->computedLastIndex(state);
+    }
+
+    RegexMatchResult result;
+    if (regexp->matchNonGlobally(state, str, result, false, lastIndex)) {
+        int e = result.m_matchResults[0][0].m_end;
+        if (option & RegExpObject::Option::Unicode) {
+            char16_t utfRes = str->charAt(e);
+            size_t eUTF = str->find(new ASCIIString((const char*)&utfRes), 0);
+            if (eUTF >= str->length()) {
+                e = str->length();
+            } else if ((int)eUTF > e || e == (int)str->length()) {
+                e = eUTF;
+            }
+        }
+
+        if (option & (RegExpObject::Option::Sticky | RegExpObject::Option::Global)) {
+            regexp->setLastIndex(state, Value(e));
+        }
+
+        return regexp->createRegExpMatchedArray(state, result, str);
+    }
+
+    if (option & (RegExpObject::Option::Sticky | RegExpObject::Option::Global)) {
+        regexp->setLastIndex(state, Value(0));
+    }
+
+    return Value(Value::Null);
+}
+
+static Value regExpExec(ExecutionState& state, Object* R, String* S)
+{
+    ASSERT(R->isObject());
+    ASSERT(S->isString());
+    Value exec = R->get(state, ObjectPropertyName(state.context()->staticStrings().exec)).value(state, R);
+    Value arg[1] = { S };
+    if (exec.isCallable()) {
+        Value result = Object::call(state, exec, R, 1, arg);
+        if (result.isNull() || result.isObject()) {
+            return result;
+        }
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().test.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    return builtinRegExpExec(state, R, 1, arg, nullptr);
+}
+
+static Value builtinRegExpTest(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, RegExp, test);
+    if (!thisObject->isRegExpObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().test.string(), ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+    }
+    RegExpObject* regexp = thisObject->asRegExpObject();
+    unsigned int option = regexp->option();
+    String* str = argv[0].toString(state);
+    uint64_t lastIndex = 0;
+    if (option & (RegExpObject::Global | RegExpObject::Sticky)) {
+        lastIndex = regexp->computedLastIndex(state);
+        if (lastIndex > str->length()) {
+            regexp->setLastIndex(state, Value(0));
+            return Value(false);
+        }
+    }
+
+    RegexMatchResult result;
+    bool testResult = regexp->match(state, str, result, true, lastIndex);
+    return Value(testResult);
+}
+
+static Value builtinRegExpToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+
+    Object* thisObject = thisValue.asObject();
+    StringBuilder builder;
+    String* pattern = thisObject->get(state, state.context()->staticStrings().source).value(state, thisObject).toString(state);
+    Value flagsValue = thisObject->get(state, state.context()->staticStrings().flags).value(state, thisObject);
+
+    builder.appendString("/");
+    builder.appendString(pattern);
+    builder.appendString("/");
+
+    if (!flagsValue.isUndefined()) {
+        builder.appendString(flagsValue.toString(state));
+    } else {
+        builder.appendString("\0");
+    }
+
+    return builder.finalize(&state);
+}
+
+static Value builtinRegExpCompile(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isRegExpObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+    }
+
+    if (argv[0].isObject() && argv[0].asObject()->isRegExpObject()) {
+        if (!argv[1].isUndefined()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot supply flags when constructing one RegExp from another");
+        } else {
+            RegExpObject* retVal = thisValue.asPointerValue()->asObject()->asRegExpObject();
+            RegExpObject* patternRegExp = argv[0].asPointerValue()->asObject()->asRegExpObject();
+            if (patternRegExp->regexpOptionString() != nullptr) {
+                retVal->init(state, patternRegExp->source(), patternRegExp->regexpOptionString());
+            } else {
+                retVal->init(state, patternRegExp->source());
+            }
+            return retVal;
+        }
+    }
+
+    RegExpObject* retVal = thisValue.asPointerValue()->asObject()->asRegExpObject();
+    String* pattern_str = argv[0].isUndefined() ? String::emptyString : argv[0].toString(state);
+    String* flags_str = argv[1].isUndefined() ? String::emptyString : argv[1].toString(state);
+    retVal->init(state, pattern_str, flags_str);
+    return retVal;
+}
+static Value builtinRegExpSearch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // $21.2.5.9 RegExp.prototype[@@search]
+    RESOLVE_THIS_BINDING_TO_OBJECT(rx, Object, search);
+    String* s = argv[0].toString(state);
+    Value previousLastIndex = rx->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, thisValue);
+    if (!previousLastIndex.equalsToByTheSameValueAlgorithm(state, Value(0))) {
+        rx->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), Value(0), thisValue);
+    }
+    Value result = regExpExec(state, rx, s);
+
+    Value currentLastIndex = rx->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, thisValue);
+    if (!previousLastIndex.equalsToByTheSameValueAlgorithm(state, currentLastIndex)) {
+        rx->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), previousLastIndex, thisValue);
+    }
+    if (result.isNull()) {
+        return Value(-1);
+    } else {
+        return result.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, thisValue);
+    }
+}
+
+// $21.2.5.11 RegExp.prototype[@@split]
+static Value builtinRegExpSplit(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+    Object* rx = thisValue.asObject();
+    String* S = argv[0].toString(state);
+
+    // Let C be SpeciesConstructor(rx, %RegExp%).
+    Value C = rx->speciesConstructor(state, state.context()->globalObject()->regexp());
+
+    // Let flags be ToString(Get(rx, "flags")).
+    String* flags = rx->get(state, ObjectPropertyName(state.context()->staticStrings().flags)).value(state, rx).toString(state);
+    bool unicodeMatching = false;
+
+    String* newFlags;
+    // If flags contains "u", let unicodeMatching be true.
+    if (flags->find("u") != SIZE_MAX) {
+        unicodeMatching = true;
+    }
+
+    // If flags contains "y", let newFlags be flags.
+    // Else, let newFlags be the string that is the concatenation of flags and "y".
+    StringBuilder builder;
+    builder.appendString(flags);
+    if (flags->find("y") == SIZE_MAX) {
+        builder.appendString("y");
+    }
+    newFlags = builder.finalize();
+
+    // Let splitter be Construct(C, <<rx, newFlags>>).
+    Value params[2] = { rx, newFlags };
+    Object* splitter = Object::construct(state, C, 2, params).toObject(state);
+
+    // Let A be ArrayCreate(0).
+    ArrayObject* A = new ArrayObject(state);
+
+    // Let lengthA be 0.
+    size_t lengthA = 0;
+    // If limit is undefined, let lim be 2^53–1; else let lim be ToLength(limit).
+    // Note: using toUint32() here since toLength() returns 0 for negative values, which leads to incorrect behavior.
+    uint64_t lim = argc > 1 && !argv[1].isUndefined() ? argv[1].toUint32(state) : (1ULL << 53) - 1;
+
+    // Let size be the number of elements in S.
+    size_t size = S->length();
+    // Let p be 0.
+    size_t p = 0;
+    // If lim = 0, return A.
+    if (lim == 0) {
+        return A;
+    }
+
+    Value z;
+    // If size = 0, then
+    if (size == 0) {
+        // Let z be RegExpExec(splitter, S).
+
+        Value z = regExpExec(state, splitter, S);
+        // If z is not null, return A.
+        if (!z.isNull()) {
+            return A;
+        }
+        // Perform CreateDataProperty(A, "0", S).
+        A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, (ObjectPropertyDescriptor::AllPresent)));
+        // Return A.
+        return A;
+    }
+
+    // Let q be p.
+    size_t q = p;
+    // Repeat, while q < size.
+    while (q < size) {
+        // Let setStatus be Set(splitter, "lastIndex", q, true).
+        splitter->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), Value(q), splitter);
+        // Let z be RegExpExec(splitter, S).
+        Value z = regExpExec(state, splitter, S);
+        // If z is null, let q be AdvanceStringIndex(S, q, unicodeMatching).
+        if (z.isNull()) {
+            q = S->advanceStringIndex(q, unicodeMatching);
+        } else {
+            // Else z is not null,
+            // Let e be ToLength(Get(splitter, "lastIndex")).
+            size_t e = splitter->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, splitter).toLength(state);
+            if (e > size) {
+                e = size;
+            }
+            // If e = p, let q be AdvanceStringIndex(S, q, unicodeMatching).
+            if (e == p) {
+                q = S->advanceStringIndex(q, unicodeMatching);
+            } else {
+                // Else e != p
+                size_t matchStart = z.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, z).toNumber(state);
+
+                if (matchStart >= S->length()) {
+                    matchStart = p;
+                }
+                // Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through q (exclusive).
+                String* T = S->substring(p, matchStart);
+                // Perform CreateDataProperty(A, ToString(lengthA), T).
+                A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(T, (ObjectPropertyDescriptor::AllPresent)));
+                // Let lengthA be lengthA + 1.
+                lengthA++;
+                // If lengthA = lim, return A.
+                if (lengthA == lim) {
+                    return A;
+                }
+                // Let p be e.
+                p = e;
+                // Let numberOfCaptures be ToLength(Get(z, "length")).
+                size_t numberOfCaptures = z.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, z).toLength(state);
+                // Let numberOfCaptures be max(numberOfCaptures - 1, 0).
+                numberOfCaptures = std::max(numberOfCaptures - 1, (size_t)0);
+                if (numberOfCaptures == SIZE_MAX) {
+                    numberOfCaptures = 0;
+                }
+                // Let i be 1.
+                // Repeat, while i <= numberOfCaptures.
+                for (size_t i = 1; i <= numberOfCaptures; i++) {
+                    // Let nextCapture be Get(z, ToString(i)).
+                    Value nextCapture = z.asObject()->get(state, ObjectPropertyName(state, Value(i).toString(state))).value(state, z);
+                    // Perform CreateDataProperty(A, ToString(lengthA), nextCapture).
+                    A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(nextCapture, ObjectPropertyDescriptor::AllPresent));
+                    // Let lengthA be lengthA + 1.
+                    lengthA++;
+                    // If lengthA = lim, return A.
+                    if (lengthA == lim) {
+                        return A;
+                    }
+                }
+                // Let q be p.
+                q = p;
+            }
+        }
+    }
+
+    // Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through size (exclusive).
+    String* T = S->substring(p, size);
+    // Perform CreateDataProperty(A, ToString(lengthA), T ).
+    A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
+    // Return A.
+    return A;
+}
+
+static Value builtinRegExpReplace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ASSERT(argc == 0 || argv != nullptr);
+    Value rx = thisValue;
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+    String* str = argv[0].toString(state);
+    Value replaceValue = argv[1];
+    size_t lengthStr = str->length();
+    bool functionalReplace = replaceValue.isCallable();
+    bool fullUnicode = false;
+    String* replacement = String::emptyString;
+    size_t nextSourcePosition = 0;
+    StringBuilder builder;
+
+    if (!functionalReplace) {
+        replaceValue = replaceValue.toString(state);
+    }
+    bool global = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().global)).value(state, rx).toBoolean(state);
+    if (global) {
+        fullUnicode = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().unicode)).value(state, rx).toBoolean(state);
+        rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(0), rx);
+    }
+    ValueVectorWithInlineStorage results;
+    Value strValue = Value(str);
+    while (true) {
+        Value result = regExpExec(state, rx.toObject(state), str);
+        if (result.isNull()) {
+            break;
+        }
+        results.push_back(result);
+        if (!global) {
+            break;
+        }
+        Value matchStr = result.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, result);
+        if (matchStr.toString(state)->length() == 0 && global) {
+            uint64_t thisIndex = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, rx).toLength(state);
+            uint64_t nextIndex = str->advanceStringIndex(thisIndex, fullUnicode);
+            rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(nextIndex), rx);
+        }
+    }
+
+    size_t resultSize = results.size();
+    for (uint i = 0; i < resultSize; i++) {
+        Object* result = results[i].toObject(state);
+        size_t nCaptures = result->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, result).toLength(state) - 1;
+
+        if (nCaptures == SIZE_MAX) {
+            nCaptures = 0;
+        }
+        String* matched = result->get(state, ObjectPropertyName(state, Value(0))).value(state, result).toString(state);
+        size_t matchLength = matched->length();
+        size_t position = result->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, result).toInteger(state);
+
+        if (position > lengthStr) {
+            position = lengthStr;
+        }
+        if (position == SIZE_MAX) {
+            position = 0;
+        }
+        size_t n = 1;
+        StringVector captures;
+        Value* replacerArgs = nullptr;
+        Value namedCaptures = result->get(state, ObjectPropertyName(state, state.context()->staticStrings().groups)).value(state, result);
+        size_t replacerArgsSize = nCaptures + 3;
+        if (functionalReplace) {
+            if (namedCaptures.isUndefined()) {
+                replacerArgs = ALLOCA(sizeof(Value) * (nCaptures + 3), Value, state);
+            } else {
+                replacerArgs = ALLOCA(sizeof(Value) * (nCaptures + 4), Value, state);
+                replacerArgsSize++;
+                replacerArgs[nCaptures + 3] = namedCaptures;
+            }
+            replacerArgs[0] = matched;
+        }
+        while (n <= nCaptures) {
+            Value capN = result->get(state, ObjectPropertyName(state, Value(n))).value(state, result);
+            if (!capN.isUndefined()) {
+                captures.push_back(capN.toString(state));
+            } else {
+                captures.push_back(String::emptyString);
+            }
+            if (functionalReplace) {
+                replacerArgs[n] = capN;
+            }
+            n++;
+        }
+        if (functionalReplace) {
+            replacerArgs[nCaptures + 1] = Value((size_t)position);
+            replacerArgs[nCaptures + 2] = Value(str);
+
+            replacement = Object::call(state, replaceValue, Value(), replacerArgsSize, replacerArgs).toString(state);
+        } else {
+            replacement = String::getSubstitution(state, matched, str, position, captures, namedCaptures, replaceValue.toString(state));
+        }
+        if (position >= nextSourcePosition) {
+            builder.appendSubString(str, nextSourcePosition, position);
+            builder.appendSubString(replacement, 0, replacement->length());
+            nextSourcePosition = position + matchLength;
+        }
+    }
+    if (nextSourcePosition >= lengthStr) {
+        return Value(builder.finalize(&state));
+    }
+    builder.appendSubString(str, nextSourcePosition, str->length());
+    return Value(builder.finalize(&state));
+}
+
+static Value builtinRegExpMatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value rx = thisValue;
+
+    if (!rx.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true,
+                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+
+    String* str = argv[0].toString(state);
+    ASSERT(str != nullptr);
+
+    //21.2.5.6.8
+    bool global = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().global)).value(state, rx).toBoolean(state);
+
+    if (!global) {
+        return regExpExec(state, rx.asObject(), str);
+    }
+
+    bool fullUnicode = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().unicode)).value(state, rx).toBoolean(state);
+    rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(0), rx);
+    ArrayObject* A = new ArrayObject(state);
+    size_t n = 0;
+
+    //21.2.5.6.8.g.i
+    while (true) {
+        //21.2.5.6.8.g.i
+        Value result = regExpExec(state, rx.asObject(), str);
+        //21.2.5.6.8.g.iii
+        if (result.isNull()) {
+            if (n == 0) {
+                return Value(Value::Null);
+            }
+            return A;
+        } else {
+            //21.2.5.6.8.g.iv
+            Value matchStr = result.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, result).toString(state);
+            A->defineOwnProperty(state, ObjectPropertyName(state, Value(n).toString(state)), ObjectPropertyDescriptor(Value(matchStr), (ObjectPropertyDescriptor::PresentAttribute::AllPresent)));
+            if (matchStr.asString()->length() == 0) {
+                //21.2.5.6.8.g.iv.5
+                uint64_t thisIndex = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, rx).toLength(state);
+                uint64_t nextIndex = str->advanceStringIndex(thisIndex, fullUnicode);
+                rx.asObject()->setThrowsException(state, state.context()->staticStrings().lastIndex, Value(nextIndex), rx);
+            }
+            n++;
+        }
+    }
+}
+
+static Value builtinRegExpMatchAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true,
+                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+    bool global = false;
+    bool unicode = false;
+    Object* thisObj = thisValue.asObject();
+    String* s = argv[0].toString(state);
+    String* flags = thisObj->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, thisObj).toString(state);
+
+    Value c = thisObj->speciesConstructor(state, state.context()->globalObject()->regexp());
+    Value arguments[] = { thisObj, flags };
+    Object* matcher = Object::construct(state, c, 2, arguments).toObject(state);
+
+    size_t lastIndex = thisObj->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, thisObj).toNumber(state);
+    matcher->asRegExpObject()->setLastIndex(state, Value(lastIndex));
+
+    if (flags->find("g") != SIZE_MAX) {
+        global = true;
+    }
+    if (flags->find("u") != SIZE_MAX) {
+        unicode = true;
+    }
+    return new RegExpStringIteratorObject(state, global, unicode, matcher->asRegExpObject(), s);
+}
+
+
+static Value builtinRegExpOptionGetterHelper(ExecutionState& state, Value thisValue, unsigned int option)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+
+    if (!thisValue.asObject()->isRegExpObject()) {
+        if (thisValue.asObject() == state.context()->globalObject()->regexpPrototype()) {
+            return Value();
+        } else {
+            ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+        }
+    }
+
+    return Value((bool)(thisValue.asObject()->asRegExpObject()->option() & option));
+}
+
+static Value builtinRegExpFlagsGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, "getter called on non-object");
+    }
+
+    return Value(thisValue.asObject()->optionString(state));
+}
+
+static Value builtinRegExpGlobalGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Global);
+}
+
+static Value builtinRegExpDotAllGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::DotAll);
+}
+
+static Value builtinRegExpIgnoreCaseGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::IgnoreCase);
+}
+
+static Value builtinRegExpMultiLineGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::MultiLine);
+}
+
+static Value builtinRegExpSourceGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject);
+    }
+
+    if (!thisValue.asObject()->isRegExpObject()) {
+        if (thisValue.asObject() == state.context()->globalObject()->regexpPrototype()) {
+            return Value(state.context()->staticStrings().defaultRegExpString.string());
+        } else {
+            ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+        }
+    }
+
+    return Value(thisValue.asObject()->asRegExpObject()->source());
+}
+
+static Value builtinRegExpStickyGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Sticky);
+}
+
+static Value builtinRegExpUnicodeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Unicode);
+}
+
+
+// Legacy RegExp Features (non-standard)
+static Value builtinRegExpInputGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+    }
+    auto& status = state.context()->regexpLegacyFeatures();
+    if (!status.isValid()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);
+    }
+    return status.input;
+}
+
+static Value builtinRegExpInputSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
+    }
+    state.context()->regexpLegacyFeatures().input = argv[0].toString(state);
+    return Value();
+}
+
+#define REGEXP_LEGACY_FEATURES(F) \
+    F(LastMatch, lastMatch)       \
+    F(LastParen, lastParen)       \
+    F(LeftContext, leftContext)   \
+    F(RightContext, rightContext)
+
+#define REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(F) \
+    F(1)                                        \
+    F(2)                                        \
+    F(3)                                        \
+    F(4)                                        \
+    F(5)                                        \
+    F(6)                                        \
+    F(7)                                        \
+    F(8)                                        \
+    F(9)
+
+#define DEFINE_LEGACY_FEATURE_GETTER(NAME, name)                                                                                            \
+    static Value builtinRegExp##NAME##Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                       \
+        if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {                                   \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);         \
+        }                                                                                                                                   \
+                                                                                                                                            \
+        auto& status = state.context()->regexpLegacyFeatures();                                                                             \
+        if (!status.isValid()) {                                                                                                            \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);               \
+        }                                                                                                                                   \
+        return new StringView(status.name);                                                                                                 \
+    }
+
+#define DEFINE_LEGACY_DOLLAR_NUMBER_FEATURE_GETTER(number)                                                                                          \
+    static Value builtinRegExpDollar##number##Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                               \
+        if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {                                           \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);                 \
+        }                                                                                                                                           \
+        auto& status = state.context()->regexpLegacyFeatures();                                                                                     \
+        if (!status.isValid()) {                                                                                                                    \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);                       \
+        }                                                                                                                                           \
+        return (status.dollarCount < number) ? String::emptyString : new StringView(status.dollars[number - 1]);                                    \
+    }
+
+REGEXP_LEGACY_FEATURES(DEFINE_LEGACY_FEATURE_GETTER);
+REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(DEFINE_LEGACY_DOLLAR_NUMBER_FEATURE_GETTER);
+
+static Value builtinRegExpStringIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isRegExpStringIteratorObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExpStringIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    RegExpStringIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asRegExpStringIteratorObject();
+    return iter->next(state);
+}
+
+std::pair<Value, bool> RegExpStringIteratorObject::advance(ExecutionState& state)
+{
+    if (m_isDone) {
+        return std::make_pair(Value(), true);
+    }
+    RegExpObject* r = m_regexp;
+    String* s = m_string;
+    bool global = m_isGlobal;
+    bool unicode = m_isUnicode;
+    Value match = regExpExec(state, r, s);
+
+    if (match.isNull()) {
+        m_isDone = true;
+        return std::make_pair(Value(), true);
+    }
+    if (global) {
+        String* matchStr = match.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, match).toString(state);
+        if (matchStr->length() == 0) {
+            //21.2.5.6.8.g.iv.5
+            uint64_t thisIndex = r->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, r).toLength(state);
+            uint64_t nextIndex = s->advanceStringIndex(thisIndex, unicode);
+            r->setThrowsException(state, state.context()->staticStrings().lastIndex, Value(nextIndex), r);
+        }
+        return std::make_pair(match, false);
+    }
+    m_isDone = true;
+    return std::make_pair(match, false);
+}
+
+void GlobalObject::installRegExp(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    m_regexp = new NativeFunctionObject(state, NativeFunctionInfo(strings->RegExp, builtinRegExpConstructor, 2), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_regexp->setGlobalIntrinsicObject(state);
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexp->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    // Legacy RegExp Features (non-standard)
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpInputGetter, 0, NativeFunctionInfo::Strict)),
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->set, builtinRegExpInputSetter, 1, NativeFunctionInfo::Strict)));
+        m_regexp->defineOwnProperty(state, strings->input, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+        m_regexp->defineOwnProperty(state, strings->$_, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLastMatchGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        m_regexp->defineOwnProperty(state, strings->lastMatch, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+        m_regexp->defineOwnProperty(state, strings->$Ampersand, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLastParenGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        m_regexp->defineOwnProperty(state, strings->lastParen, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+        m_regexp->defineOwnProperty(state, strings->$PlusSign, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLeftContextGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        m_regexp->defineOwnProperty(state, strings->leftContext, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+        m_regexp->defineOwnProperty(state, strings->$GraveAccent, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    }
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpRightContextGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        m_regexp->defineOwnProperty(state, strings->rightContext, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+        m_regexp->defineOwnProperty(state, strings->$Apostrophe, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    }
+
+#define DEFINE_LEGACY_DOLLAR_NUMBER_ATTR(number)                                                                                                                                           \
+    {                                                                                                                                                                                      \
+        JSGetterSetter gs(                                                                                                                                                                 \
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpDollar##number##Getter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));              \
+        m_regexp->defineOwnProperty(state, strings->$##number, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent))); \
+    }
+
+    REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(DEFINE_LEGACY_DOLLAR_NUMBER_ATTR);
+
+    m_regexpPrototype = new Object(state);
+    m_regexpPrototype->setGlobalIntrinsicObject(state, true);
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFlags, builtinRegExpFlagsGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->flags), desc);
+    }
+
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getGlobal, builtinRegExpGlobalGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->global), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getDotAll, builtinRegExpDotAllGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->dotAll), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getIgnoreCase, builtinRegExpIgnoreCaseGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->ignoreCase), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getMultiline, builtinRegExpMultiLineGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->multiline), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getSource, builtinRegExpSourceGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->source), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getSticky, builtinRegExpStickyGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->sticky), desc);
+    }
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getUnicode, builtinRegExpUnicodeGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->unicode), desc);
+    }
+
+    m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_regexp->setFunctionPrototype(state, m_regexpPrototype);
+
+    // $21.2.5.2 RegExp.prototype.exec
+    m_regexpExecMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->exec, builtinRegExpExec, 1, NativeFunctionInfo::Strict));
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->exec),
+                                                        ObjectPropertyDescriptor(m_regexpExecMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $21.2.5.13 RegExp.prototype.test
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->test),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->test, builtinRegExpTest, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $21.2.5.14 RegExp.prototype.toString
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinRegExpToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    // $B.2.5.1 RegExp.prototype.compile
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->compile),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->compile, builtinRegExpCompile, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.2.5.9 RegExp.prototype[@@search]
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolSearch, builtinRegExpSearch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.2.5.11 RegExp.prototype[@@split]
+    m_regexpSplitMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolSplit, builtinRegExpSplit, 2, NativeFunctionInfo::Strict));
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().split),
+                                                        ObjectPropertyDescriptor(m_regexpSplitMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.2.5.8 RegExp.prototype [@@replace]
+    m_regexpReplaceMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolReplace, builtinRegExpReplace, 2, NativeFunctionInfo::Strict));
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace),
+                                                        ObjectPropertyDescriptor(m_regexpReplaceMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.2.5.6 RegExp.prototype[@@match]
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolMatch, builtinRegExpMatch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolMatchAll, builtinRegExpMatchAll, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_regexpStringIteratorPrototype = new Object(state, m_iteratorPrototype);
+    m_regexpStringIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_regexpStringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinRegExpStringIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_regexpStringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                      ObjectPropertyDescriptor(Value(String::fromASCII("RegExp String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(strings->RegExp),
+                      ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSet.cpp
new file mode 100644 (file)
index 0000000..31c6823
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/SetObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, throw a TypeError exception.
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    // Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%SetPrototype%", « [[SetData]] »).
+    // Set set's [[SetData]] internal slot to a new empty List.
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->setPrototype();
+    });
+    SetObject* set = new SetObject(state, proto);
+
+    // If iterable is not present, let iterable be undefined.
+    Value iterable;
+    if (argc >= 1) {
+        iterable = argv[0];
+    }
+
+    // If iterable is either undefined or null, return set.
+    if (iterable.isUndefinedOrNull()) {
+        return set;
+    }
+
+    // Let adder be ? Get(set, "add").
+    Value adder = set->get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set);
+    // If IsCallable(adder) is false, throw a TypeError exception.
+    if (!adder.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
+    }
+    // Let iteratorRecord be ? GetIterator(iterable).
+    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
+
+    // Repeat
+    while (true) {
+        // Let next be ? IteratorStep(iteratorRecord).
+        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
+        // If next is false, return set.
+        if (!next.hasValue()) {
+            return set;
+        }
+        // Let nextValue be ? IteratorValue(next).
+        Value nextValue = IteratorObject::iteratorValue(state, next.value());
+
+        // Let status be Call(adder, set, « nextValue »).
+        try {
+            Value argv[1] = { nextValue };
+            Object::call(state, adder, set, 1, argv);
+        } catch (const Value& v) {
+            // we should save thrown value bdwgc cannot track thrown value
+            Value exceptionValue = v;
+            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
+            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+        }
+    }
+
+    return set;
+}
+
+#define RESOLVE_THIS_BINDING_TO_SET(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                          \
+    if (!thisValue.isObject() || !thisValue.asObject()->isSetObject()) {                                                                                                                                                                                 \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                    \
+    SetObject* NAME = thisValue.asObject()->asSetObject();
+
+static Value builtinSetAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, add);
+    S->add(state, argv[0]);
+    return S;
+}
+
+static Value builtinSetClear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, clear);
+    S->clear(state);
+    return Value();
+}
+
+static Value builtinSetDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, stringDelete);
+    return Value(S->deleteOperation(state, argv[0]));
+}
+
+static Value builtinSetHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, has);
+    return Value(S->has(state, argv[0]));
+}
+
+static Value builtinSetForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let S be the this value.
+    // If Type(S) is not Object, throw a TypeError exception.
+    // If S does not have a [[SetData]] internal slot, throw a TypeError exception.
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, forEach);
+
+    Value callbackfn = argv[0];
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Set.string(), true, state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc >= 2) {
+        T = argv[1];
+    }
+    // Let entries be the List that is the value of S's [[SetData]] internal slot.
+    const SetObject::SetObjectData& entries = S->storage();
+    // Repeat for each e that is an element of entries, in original insertion order
+    for (size_t i = 0; i < entries.size(); i++) {
+        Value e = entries[i];
+        // If e is not empty, then
+        if (!e.isEmpty()) {
+            // If e.[[Key]] is not empty, then
+            // Perform ? Call(callbackfn, T, « e, e, S »).
+            Value argv[3] = { Value(e), Value(e), Value(S) };
+            Object::call(state, callbackfn, T, 3, argv);
+        }
+    }
+
+    return Value();
+}
+
+static Value builtinSetValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, values);
+    return S->values(state);
+}
+
+static Value builtinSetEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, entries);
+    return S->entries(state);
+}
+
+static Value builtinSetSizeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SET(S, Set, size);
+    return Value(S->size(state));
+}
+
+static Value builtinSetIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isSetIteratorObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SetIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    SetIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asSetIteratorObject();
+    return iter->next(state);
+}
+
+void GlobalObject::installSet(ExecutionState& state)
+{
+    m_set = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Set, builtinSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_set->setGlobalIntrinsicObject(state);
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_set->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    m_setPrototype = new Object(state);
+    m_setPrototype->setGlobalIntrinsicObject(state, true);
+    m_setPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clear),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinSetClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinSetForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    auto valuesFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinSetValues, 0, NativeFunctionInfo::Strict));
+    auto values = ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values), values);
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys), values);
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
+                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinSetEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                     ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                     ObjectPropertyDescriptor(Value(state.context()->staticStrings().Set.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+    JSGetterSetter gs(
+        new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("get size")), builtinSetSizeGetter, 0, NativeFunctionInfo::Strict)),
+        Value(Value::EmptyValue));
+    ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+    m_setPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);
+
+    m_setIteratorPrototype = new Object(state, m_iteratorPrototype);
+    m_setIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_setIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinSetIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_setIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                             ObjectPropertyDescriptor(Value(String::fromASCII("Set Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_set->setFunctionPrototype(state, m_setPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Set),
+                      ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSharedArrayBuffer.cpp
new file mode 100644 (file)
index 0000000..fc4ddb0
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#if defined(ENABLE_THREADING)
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/SharedArrayBufferObject.h"
+
+namespace Escargot {
+
+// https://262.ecma-international.org/#sec-sharedarraybuffer-constructor
+static Value builtinSharedArrayBufferConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    uint64_t byteLength = argv[0].toIndex(state);
+    if (byteLength == Value::InvalidIndexValue) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().SharedArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
+    }
+
+    return SharedArrayBufferObject::allocateSharedArrayBuffer(state, newTarget.value(), byteLength);
+}
+
+// https://262.ecma-international.org/#sec-get-sharedarraybuffer.prototype.bytelength
+static Value builtinSharedArrayBufferByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isSharedArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    SharedArrayBufferObject* obj = thisValue.asObject()->asSharedArrayBufferObject();
+    return Value(obj->byteLength());
+}
+
+// https://262.ecma-international.org/#sec-sharedarraybuffer.prototype.slice
+static Value builtinSharedArrayBufferSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isSharedArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+
+    SharedArrayBufferObject* O = thisValue.asObject()->asSharedArrayBufferObject();
+    double len = O->byteLength();
+    double relativeStart = argv[0].toInteger(state);
+    size_t first = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, len);
+    double relativeEnd = argv[1].isUndefined() ? len : argv[1].toInteger(state);
+    double final_ = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, len);
+    size_t newLen = std::max((int)final_ - (int)first, 0);
+
+    Value constructor = O->speciesConstructor(state, state.context()->globalObject()->sharedArrayBuffer());
+    Value arguments[] = { Value(newLen) };
+    Object* newValue = Object::construct(state, constructor, 1, arguments).toObject(state);
+    if (!newValue->isSharedArrayBufferObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor SharedArrayBuffer is not valid SharedArrayBuffer");
+    }
+
+    SharedArrayBufferObject* newBuffer = newValue->asSharedArrayBufferObject();
+    if ((newBuffer->data() == O->data()) || (newBuffer->byteLength() < newLen)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor SharedArrayBuffer is not valid SharedArrayBuffer");
+    }
+
+    newBuffer->fillData(O->data() + first, newLen);
+    return newBuffer;
+}
+
+void GlobalObject::installSharedArrayBuffer(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    m_sharedArrayBuffer = new NativeFunctionObject(state, NativeFunctionInfo(strings->SharedArrayBuffer, builtinSharedArrayBufferConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_sharedArrayBuffer->setGlobalIntrinsicObject(state);
+
+    m_sharedArrayBufferPrototype = new Object(state, m_objectPrototype);
+    m_sharedArrayBufferPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_sharedArrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    m_sharedArrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                   ObjectPropertyDescriptor(Value(strings->SharedArrayBuffer.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_sharedArrayBuffer->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+    JSGetterSetter gs(
+        new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinSharedArrayBufferByteLengthGetter, 0, NativeFunctionInfo::Strict)),
+        Value(Value::EmptyValue));
+    ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+    m_sharedArrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
+    m_sharedArrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
+                                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinSharedArrayBufferSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_sharedArrayBuffer->setFunctionPrototype(state, m_sharedArrayBufferPrototype);
+
+    defineOwnProperty(state, ObjectPropertyName(strings->SharedArrayBuffer),
+                      ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinString.cpp
new file mode 100644 (file)
index 0000000..0f5ebb4
--- /dev/null
@@ -0,0 +1,1833 @@
+/*
+ * Copyright (c) 2016-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/StringObject.h"
+#include "runtime/ErrorObject.h"
+#include "runtime/RegExpObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/NativeFunctionObject.h"
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+#include "intl/Intl.h"
+#include "intl/IntlCollator.h"
+#endif
+
+#include "WTFBridge.h"
+#include "Yarr.h"
+#include "YarrPattern.h"
+
+namespace Escargot {
+
+static Value builtinStringConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    String* s = String::emptyString;
+    if (argc > 0) {
+        Value value = argv[0];
+        if (!newTarget.hasValue() && value.isSymbol()) {
+            return value.asSymbol()->symbolDescriptiveString();
+        } else {
+            s = value.toString(state);
+        }
+    }
+    if (!newTarget.hasValue()) {
+        return s;
+    }
+
+    // StringCreate(s, ? GetPrototypeFromConstructor(NewTarget, "%StringPrototype%")).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->stringPrototype();
+    });
+    return new StringObject(state, proto, s);
+}
+
+static Value builtinStringToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isObject() && thisValue.asObject()->isStringObject()) {
+        return thisValue.asObject()->asStringObject()->primitiveValue();
+    }
+
+    if (thisValue.isString())
+        return thisValue.toString(state);
+
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotString);
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static Value builtinStringIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, indexOf);
+    String* searchStr = argv[0].toString(state);
+
+    Value val;
+    if (argc > 1) {
+        val = argv[1];
+    }
+    double pos;
+    if (val.isUndefined()) {
+        pos = 0;
+    } else {
+        pos = val.toInteger(state);
+    }
+    if (pos == std::numeric_limits<double>::infinity() || std::isnan(pos)) {
+        pos = std::numeric_limits<double>::quiet_NaN();
+    }
+    if (pos == -std::numeric_limits<double>::infinity()) {
+        pos = 0;
+    }
+    size_t len = str->length();
+    size_t start = std::min(std::max(pos, 0.0), (double)len);
+    size_t result = str->find(searchStr, start);
+
+    if (result == SIZE_MAX)
+        return Value(-1);
+    else
+        return Value(result);
+}
+
+static Value builtinStringLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let S be ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, lastIndexOf);
+    String* searchStr = argv[0].toString(state);
+
+    double numPos;
+    if (argc > 1) {
+        numPos = argv[1].toNumber(state);
+    } else {
+        numPos = Value().toNumber(state);
+    }
+
+    double pos;
+    // If numPos is NaN, let pos be +∞; otherwise, let pos be ToInteger(numPos).
+    if (std::isnan(numPos))
+        pos = std::numeric_limits<double>::infinity();
+    else
+        pos = numPos;
+
+    double len = S->length();
+    double start = std::min(std::max(pos, 0.0), len);
+    size_t result = S->rfind(searchStr, start);
+    if (result == SIZE_MAX) {
+        return Value(-1);
+    }
+    return Value(result);
+}
+
+static Value builtinStringLocaleCompare(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, localeCompare);
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    String* That = argv[0].toString(state);
+    Value locales, options;
+
+    if (argc >= 2) {
+        locales = argv[1];
+    }
+    if (argc >= 3) {
+        options = argv[2];
+    }
+
+    Object* collator = IntlCollator::create(state, state.context(), locales, options);
+
+    return Value(IntlCollator::compare(state, collator, S, That));
+#else
+    String* That = argv[0].toString(state);
+    return Value(stringCompare(*S, *That));
+#endif
+}
+
+static Value builtinStringSubstring(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, substring);
+    if (argc == 0) {
+        return str;
+    } else {
+        int len = str->length();
+        double doubleStart = argv[0].toNumber(state);
+        Value end = argv[1];
+        double doubleEnd = (argc < 2 || end.isUndefined()) ? len : end.toNumber(state);
+        doubleStart = (std::isnan(doubleStart)) ? 0 : doubleStart;
+        doubleEnd = (std::isnan(doubleEnd)) ? 0 : doubleEnd;
+
+        double finalStart = (int)trunc(std::min(std::max(doubleStart, 0.0), (double)len));
+        double finalEnd = (int)trunc(std::min(std::max(doubleEnd, 0.0), (double)len));
+        size_t from = std::min(finalStart, finalEnd);
+        size_t to = std::max(finalStart, finalEnd);
+        ASSERT(from <= to);
+        if (to - from == 1) {
+            char16_t c = str->charAt(from);
+            if (c < ESCARGOT_ASCII_TABLE_MAX) {
+                return state.context()->staticStrings().asciiTable[c].string();
+            }
+        }
+        return str->substring(from, to);
+    }
+}
+
+static Value builtinStringMatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+
+    Value regexp = argv[0];
+    if (!regexp.isUndefinedOrNull()) {
+        Value matcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match));
+        if (!matcher.isUndefined()) {
+            Value args[1] = { thisValue };
+            return Object::call(state, matcher, regexp, 1, args);
+        }
+    }
+
+    String* S = thisValue.toString(state);
+    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), String::emptyString);
+    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match)).value(state, rx);
+    Value args[1] = { Value(S) };
+    return Object::call(state, func, rx, 1, args);
+}
+
+static Value builtinStringMatchAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+
+    Value regexp = argv[0];
+    if (!regexp.isUndefinedOrNull()) {
+        if (regexp.isObject() && regexp.asObject()->isRegExpObject()) {
+            String* flags = regexp.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, regexp).toString(state);
+            if (flags->find("g") == SIZE_MAX) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+            }
+        }
+        Value matcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll));
+        if (!matcher.isUndefined()) {
+            Value args[1] = { thisValue };
+            return Object::call(state, matcher, regexp, 1, args);
+        }
+    }
+    String* S = thisValue.toString(state);
+    StringBuilder builder;
+    builder.appendChar('g');
+    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), builder.finalize());
+    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll)).value(state, rx);
+    Value args[1] = { Value(S) };
+    return Object::call(state, func, rx, 1, args);
+}
+
+#if defined(ENABLE_ICU)
+static Value builtinStringNormalize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    enum NormalizationForm {
+        NFC,
+        NFD,
+        NFKC,
+        NFKD
+    };
+
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, normalize);
+    Value argument = Value();
+    if (argc > 0) {
+        argument = argv[0];
+    }
+    NormalizationForm form = NFC;
+    if (LIKELY(!argument.isUndefined())) {
+        String* formString = argument.toString(state);
+        if (formString->equals("NFC")) {
+            form = NFC;
+        } else if (formString->equals("NFD")) {
+            form = NFD;
+        } else if (formString->equals("NFKC")) {
+            form = NFKC;
+        } else if (formString->equals("NFKD")) {
+            form = NFKD;
+        } else {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid normalization form");
+            return Value();
+        }
+    }
+    if (str->length() == 0) {
+        return Value(str);
+    }
+
+    auto utf16Str = str->toUTF16StringData();
+    UErrorCode status = U_ZERO_ERROR;
+    const UNormalizer2* normalizer = nullptr;
+    switch (form) {
+    case NFC:
+        normalizer = unorm2_getNFCInstance(&status);
+        break;
+    case NFD:
+        normalizer = unorm2_getNFDInstance(&status);
+        break;
+    case NFKC:
+        normalizer = unorm2_getNFKCInstance(&status);
+        break;
+    case NFKD:
+        normalizer = unorm2_getNFKDInstance(&status);
+        break;
+    default:
+        break;
+    }
+    if (!normalizer || U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
+        return Value();
+    }
+    int32_t normalizedStringLength = unorm2_normalize(normalizer, (const UChar*)utf16Str.data(), utf16Str.length(), nullptr, 0, &status);
+
+    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
+        // when normalize fails.
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
+        return Value();
+    }
+    UTF16StringData ret;
+    ret.resizeWithUninitializedValues(normalizedStringLength);
+    status = U_ZERO_ERROR;
+    unorm2_normalize(normalizer, (const UChar*)utf16Str.data(), utf16Str.length(), (UChar*)ret.data(), normalizedStringLength, &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
+        return Value();
+    }
+    return new UTF16String(std::move(ret));
+}
+#endif // ENABLE_ICU
+
+static Value builtinStringRepeat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, repeat);
+    Value argument = argv[0];
+    int32_t repeatCount;
+    double count = argument.toInteger(state);
+    double newStringLength = str->length() * count;
+    if (count < 0 || count == std::numeric_limits<double>::infinity() || newStringLength > STRING_MAXIMUM_LENGTH) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid count number of String repeat method");
+    }
+
+    if (newStringLength == 0) {
+        return String::emptyString;
+    }
+
+    repeatCount = static_cast<int32_t>(count);
+
+    StringBuilder builder;
+    for (int i = 0; i < repeatCount; i++) {
+        builder.appendString(str);
+    }
+    return builder.finalize();
+}
+
+static Value builtinStringReplace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+
+    Value searchValue = argv[0];
+    Value replaceValue = argv[1];
+
+    bool isSearchValueRegExp = searchValue.isPointerValue() && searchValue.asPointerValue()->isRegExpObject();
+    // we should keep fast-path while performace issue is unresolved
+    bool canUseFastPath = searchValue.isString() || (isSearchValueRegExp && searchValue.asPointerValue()->asRegExpObject()->yarrPatern()->m_captureGroupNames.size() == 0);
+    if (!searchValue.isUndefinedOrNull()) {
+        Value replacer = Object::getMethod(state, searchValue, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace));
+        if (canUseFastPath && isSearchValueRegExp && replacer.isPointerValue() && replacer.asPointerValue() == state.context()->globalObject()->regexpReplaceMethod()) {
+            auto exec = searchValue.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().exec));
+            if (!exec.hasValue() || exec.value(state, searchValue) != state.context()->globalObject()->regexpExecMethod()) {
+                // this means we cannot use fast path
+                Value parameters[2] = { thisValue, replaceValue };
+                return Object::call(state, replacer, searchValue, 2, parameters);
+            }
+        } else {
+            // this means we cannot use fast path
+            if (!replacer.isUndefined()) {
+                Value parameters[2] = { thisValue, replaceValue };
+                return Object::call(state, replacer, searchValue, 2, parameters);
+            }
+        }
+    }
+
+    String* string = thisValue.toString(state);
+    String* searchString = searchValue.toString(state);
+    bool functionalReplace = replaceValue.isCallable();
+
+    if (canUseFastPath) {
+        RegexMatchResult result;
+        String* replaceString = nullptr;
+
+        if (isSearchValueRegExp) {
+            RegExpObject* regexp = searchValue.asPointerValue()->asRegExpObject();
+            bool isGlobal = regexp->option() & RegExpObject::Option::Global;
+
+            if (isGlobal) {
+                regexp->setLastIndex(state, Value(0));
+            }
+            bool testResult = regexp->matchNonGlobally(state, string, result, false, 0);
+            if (testResult) {
+                if (isGlobal) {
+                    regexp->createRegexMatchResult(state, string, result);
+                }
+            }
+        } else {
+            size_t idx = string->find(searchString);
+            if (idx != (size_t)-1) {
+                std::vector<RegexMatchResult::RegexMatchResultPiece> piece;
+                RegexMatchResult::RegexMatchResultPiece p;
+                p.m_start = idx;
+                p.m_end = idx + searchString->length();
+                piece.push_back(std::move(p));
+                result.m_matchResults.push_back(std::move(piece));
+            }
+        }
+
+        // NOTE: replaceValue.toString should be called after searchValue.toString
+        if (!functionalReplace) {
+            replaceString = replaceValue.toString(state);
+        }
+
+        // If no occurrences of searchString were found, return string.
+        if (result.m_matchResults.size() == 0) {
+            return string;
+        }
+
+        if (functionalReplace) {
+            uint32_t matchCount = result.m_matchResults.size();
+            Value callee = replaceValue;
+
+            StringBuilder builer;
+            builer.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
+
+            for (uint32_t i = 0; i < matchCount; i++) {
+                int subLen = result.m_matchResults[i].size();
+                Value* arguments;
+                arguments = ALLOCA(sizeof(Value) * (subLen + 2), Value, state);
+                for (unsigned j = 0; j < (unsigned)subLen; j++) {
+                    if (result.m_matchResults[i][j].m_start == std::numeric_limits<unsigned>::max())
+                        arguments[j] = Value();
+                    else {
+                        StringBuilder argStrBuilder;
+                        argStrBuilder.appendSubString(string, result.m_matchResults[i][j].m_start, result.m_matchResults[i][j].m_end);
+                        arguments[j] = argStrBuilder.finalize(&state);
+                    }
+                }
+                arguments[subLen] = Value((int)result.m_matchResults[i][0].m_start);
+                arguments[subLen + 1] = string;
+                // 21.1.3.14 (11) it should be called with this as undefined
+                String* res = Object::call(state, callee, Value(), subLen + 2, arguments).toString(state);
+                builer.appendSubString(res, 0, res->length());
+
+                if (i < matchCount - 1) {
+                    builer.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
+                }
+            }
+            builer.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
+            return builer.finalize(&state);
+        } else {
+            ASSERT(replaceString);
+
+            bool hasDollar = false;
+            for (size_t i = 0; i < replaceString->length(); i++) {
+                if (replaceString->charAt(i) == '$') {
+                    hasDollar = true;
+                    break;
+                }
+            }
+
+            StringBuilder builder;
+            if (!hasDollar) {
+                // flat replace
+                int32_t matchCount = result.m_matchResults.size();
+                builder.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
+                for (int32_t i = 0; i < matchCount; i++) {
+                    String* res = replaceString;
+                    builder.appendString(res);
+                    if (i < matchCount - 1) {
+                        builder.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
+                    }
+                }
+                builder.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
+            } else {
+                // dollar replace
+                int32_t matchCount = result.m_matchResults.size();
+                builder.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
+                for (int32_t i = 0; i < matchCount; i++) {
+                    for (unsigned j = 0; j < replaceString->length(); j++) {
+                        if (replaceString->charAt(j) == '$' && (j + 1) < replaceString->length()) {
+                            char16_t c = replaceString->charAt(j + 1);
+                            if (c == '$') {
+                                builder.appendChar(replaceString->charAt(j));
+                            } else if (c == '&') {
+                                builder.appendSubString(string, result.m_matchResults[i][0].m_start, result.m_matchResults[i][0].m_end);
+                            } else if (c == '\'') {
+                                builder.appendSubString(string, result.m_matchResults[i][0].m_end, string->length());
+                            } else if (c == '`') {
+                                builder.appendSubString(string, 0, result.m_matchResults[i][0].m_start);
+                            } else if ('0' <= c && c <= '9') {
+                                size_t idx = c - '0';
+                                bool usePeek = false;
+                                if (j + 2 < replaceString->length()) {
+                                    int peek = replaceString->charAt(j + 2) - '0';
+                                    if (0 <= peek && peek <= 9) {
+                                        idx *= 10;
+                                        idx += peek;
+                                        usePeek = true;
+                                    }
+                                }
+
+                                if (idx < result.m_matchResults[i].size() && idx != 0) {
+                                    builder.appendSubString(string, result.m_matchResults[i][idx].m_start, result.m_matchResults[i][idx].m_end);
+                                    if (usePeek)
+                                        j++;
+                                } else {
+                                    idx = c - '0';
+                                    if (idx < result.m_matchResults[i].size() && idx != 0) {
+                                        builder.appendSubString(string, result.m_matchResults[i][idx].m_start, result.m_matchResults[i][idx].m_end);
+                                    } else {
+                                        builder.appendChar('$');
+                                        builder.appendChar(c);
+                                    }
+                                }
+                            } else {
+                                builder.appendChar('$');
+                                builder.appendChar(c);
+                            }
+                            j++;
+                        } else {
+                            builder.appendChar(replaceString->charAt(j));
+                        }
+                    }
+                    if (i < matchCount - 1) {
+                        builder.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
+                    }
+                }
+                builder.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
+            }
+            return builder.finalize(&state);
+        }
+    } else {
+        if (!functionalReplace) {
+            replaceValue = replaceValue.toString(state);
+        }
+        size_t pos = string->find(searchString, 0);
+        String* matched = searchString;
+
+        // If no occurrences of searchString were found, return string.
+        if (pos == SIZE_MAX) {
+            return Value(string);
+        }
+        String* replStr = String::emptyString;
+        if (functionalReplace) {
+            Value parameters[3] = { Value(matched), Value(pos), Value(string) };
+            Value replValue = Object::call(state, replaceValue, Value(), 3, parameters);
+            replStr = replValue.toString(state);
+        } else {
+            StringVector captures;
+            replStr = String::getSubstitution(state, matched, string, pos, captures, Value(), replaceValue.toString(state));
+        }
+        size_t tailpos = pos + matched->length();
+        StringBuilder builder;
+        builder.appendSubString(string, 0, pos);
+        builder.appendSubString(replStr, 0, replStr->length());
+        builder.appendSubString(string, tailpos, string->length());
+        String* newString = builder.finalize(&state);
+        return Value(newString);
+    }
+}
+
+static Value builtinStringReplaceAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replaceAll.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+    Value searchValue = argv[0];
+    Value replaceValue = argv[1];
+    // If searchValue is neither undefined nor null, then
+    if (!searchValue.isUndefinedOrNull()) {
+        // If isRegExp is true, then
+        if (searchValue.isObject() && searchValue.asObject()->isRegExp(state)) {
+            Value flags = searchValue.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, searchValue);
+            if (flags.isUndefinedOrNull() || !flags.toString(state)->contains("g")) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().replaceAll.string(), true, state.context()->staticStrings().replaceAll.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+            }
+        }
+        // Let replacer be ? GetMethod(searchValue, @@replace).
+        Value replacer = Object::getMethod(state, searchValue, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace));
+        if (!replacer.isUndefined()) {
+            Value args[2] = { thisValue, replaceValue };
+            // Return ? Call(replacer, searchValue, « O, replaceValue »).
+            return Object::call(state, replacer, searchValue, 2, args);
+        }
+    }
+
+    String* string = thisValue.toString(state);
+    String* searchString = searchValue.toString(state);
+
+    bool functionalReplace = replaceValue.isCallable();
+    // If functionalReplace is false, then
+    if (!functionalReplace) {
+        replaceValue = replaceValue.toString(state);
+    }
+
+    size_t searchLength = searchString->length();
+    size_t advanceBy = (1 < searchLength) ? searchLength : 1;
+
+    std::vector<size_t> matchPositions;
+    // Let position be ! StringIndexOf(string, searchString, 0).
+    size_t position = string->find(searchString, 0);
+    // Repeat, while position is not -1
+    while (position != SIZE_MAX) {
+        matchPositions.push_back(position);
+        position = string->find(searchString, position + advanceBy);
+    }
+    size_t endOfLastMatch = 0;
+
+    StringBuilder builder;
+    String* replacement = String::emptyString;
+    // For each element p of matchPositions, do
+    for (uint i = 0; i < matchPositions.size(); i++) {
+        size_t p = matchPositions[i];
+        builder.appendSubString(string, endOfLastMatch, p);
+        // If functionalReplace is true, then
+        if (functionalReplace) {
+            Value args[3] = { searchString, Value(p), string };
+            replacement = Object::call(state, replaceValue, Value(), 3, args).toString(state);
+        } else {
+            StringVector captures;
+            replacement = String::getSubstitution(state, searchString, string, p, captures, Value(), replaceValue.asString());
+        }
+        builder.appendString(replacement);
+        endOfLastMatch = p + searchLength;
+    }
+    // If endOfLastMatch < the length of string, then
+    if (endOfLastMatch < string->length()) {
+        builder.appendSubString(string, endOfLastMatch, string->length());
+    }
+    return builder.finalize(&state);
+}
+
+static Value builtinStringSearch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().search.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+
+    Value regexp = argv[0];
+    if (!regexp.isUndefinedOrNull()) {
+        Value searcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search));
+        if (!searcher.isUndefined()) {
+            Value args[1] = { thisValue };
+            return Object::call(state, searcher, regexp, 1, args);
+        }
+    }
+
+    String* string = thisValue.toString(state);
+    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), String::emptyString);
+    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search)).value(state, rx);
+    Value args[1] = { Value(string) };
+    return Object::call(state, func, rx, 1, args);
+}
+
+static Value builtinStringSplit(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().split.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+
+    Value separator = argv[0];
+    Value limit = argv[1];
+    bool isSeparatorRegExp = separator.isPointerValue() && separator.asPointerValue()->isRegExpObject();
+
+    // If separator is neither undefined nor null, then
+    if (!separator.isUndefinedOrNull()) {
+        // Let splitter be GetMethod(separator, @@split).
+        Value splitter = Object::getMethod(state, separator, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().split));
+
+        // --- Optmize path
+        // if splitter is builtin RegExp.prototype.split and separator is RegExpObject
+        // we can use old method(ES5) below
+        if (isSeparatorRegExp && splitter.isPointerValue() && splitter.asPointerValue() == state.context()->globalObject()->regexpSplitMethod()) {
+        } else if (!splitter.isUndefined()) {
+            // If splitter is not undefined, then
+            // Return Call(splitter, separator, <<O, limit>>).
+            Value params[2] = { thisValue, limit };
+            return Object::call(state, splitter, separator, 2, params);
+        }
+    }
+
+    // Let S be ? ToString(O).
+    String* S = thisValue.toString(state);
+    // Let A be ! ArrayCreate(0).
+    ArrayObject* A = new ArrayObject(state);
+    // Let lengthA = 0.
+    size_t lengthA = 0;
+    // If limit is undefined, let lim be 2^32 - 1; else let lim be ? ToUint32(limit).
+    uint64_t lim = limit.isUndefined() ? (1ULL << 32) - 1 : limit.toUint32(state);
+    // Let s be the length of S.
+    // Let p = 0.
+    size_t s = S->length(), p = 0;
+
+    PointerValue* P;
+    if (isSeparatorRegExp) {
+        P = separator.asPointerValue()->asRegExpObject();
+    } else {
+        P = separator.toString(state);
+    }
+
+    // If lim = 0, return A.
+    if (lim == 0) {
+        return A;
+    }
+
+    if (separator.isUndefined()) {
+        A->defineOwnProperty(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, ObjectPropertyDescriptor::AllPresent));
+        return A;
+    }
+
+    std::function<Value(String*, int, String*)> splitMatchUsingStr;
+    splitMatchUsingStr = [](String* S, int q, String* R) -> Value {
+        int s = S->length();
+        int r = R->length();
+        if (q + r > s)
+            return Value(false);
+        for (int i = 0; i < r; i++)
+            if (S->charAt(q + i) != R->charAt(i))
+                return Value(false);
+        return Value(q + r);
+    };
+    if (s == 0) {
+        bool ret = true;
+        if (P->isRegExpObject()) {
+            RegexMatchResult result;
+            ret = P->asRegExpObject()->matchNonGlobally(state, S, result, false, 0);
+        } else {
+            Value z = splitMatchUsingStr(S, 0, P->asString());
+            if (z.isBoolean()) {
+                ret = z.asBoolean();
+            }
+        }
+        if (ret)
+            return A;
+        A->defineOwnProperty(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, ObjectPropertyDescriptor::AllPresent));
+        return A;
+    }
+
+    size_t q = p;
+
+    // 13
+    if (P->isRegExpObject()) {
+        RegExpObject* R = P->asRegExpObject();
+        while (q != s) {
+            RegexMatchResult result;
+            bool ret = R->matchNonGlobally(state, S, result, false, (size_t)q);
+            if (!ret) {
+                break;
+            }
+
+            if ((size_t)result.m_matchResults[0][0].m_end == p) {
+                q++;
+            } else {
+                if (result.m_matchResults[0][0].m_start >= S->length())
+                    break;
+
+                String* T = S->substring(p, result.m_matchResults[0][0].m_start);
+                A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA++)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
+                if (lengthA == lim)
+                    return A;
+                p = result.m_matchResults[0][0].m_end;
+                R->pushBackToRegExpMatchedArray(state, A, lengthA, lim, result, S);
+                if (lengthA == lim)
+                    return A;
+                q = p;
+            }
+        }
+    } else {
+        String* R = P->asString();
+        while (q != s) {
+            Value e = splitMatchUsingStr(S, q, R);
+            if (e == Value(false))
+                q++;
+            else {
+                if ((size_t)e.asInt32() == p)
+                    q++;
+                else {
+                    if (q >= S->length())
+                        break;
+
+                    String* T = S->substring(p, q);
+                    A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA++)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
+                    if (lengthA == lim)
+                        return A;
+                    p = e.asInt32();
+                    q = p;
+                }
+            }
+        }
+    }
+
+    String* T = S->substring(p, s);
+    A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
+    return A;
+}
+
+static Value builtinStringCharCodeAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, charCodeAt);
+    int position = argv[0].toInteger(state);
+    Value ret;
+    const auto& data = str->bufferAccessData();
+    if (position < 0 || position >= (int)data.length)
+        ret = Value(std::numeric_limits<double>::quiet_NaN());
+    else {
+        char16_t c;
+        if (data.has8BitContent) {
+            c = ((LChar*)data.buffer)[position];
+        } else {
+            c = ((char16_t*)data.buffer)[position];
+        }
+        ret = Value(c);
+    }
+    return ret;
+}
+
+// https://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.codepointat
+static Value builtinStringCodePointAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, codePointAt);
+    int position = argv[0].toInteger(state);
+    Value ret;
+    const auto& data = str->bufferAccessData();
+    const int size = (int)data.length;
+    if (position < 0 || position >= size)
+        return Value();
+
+    char16_t first;
+    if (data.has8BitContent) {
+        first = ((LChar*)data.buffer)[position];
+    } else {
+        first = ((char16_t*)data.buffer)[position];
+    }
+
+    if (first < 0xD800 || first > 0xDBFF || (position + 1) == size) {
+        return Value(first);
+    }
+
+    char16_t second;
+    if (data.has8BitContent) {
+        second = ((LChar*)data.buffer)[position + 1];
+    } else {
+        second = ((char16_t*)data.buffer)[position + 1];
+    }
+
+    if (second < 0xDC00 || second > 0xDFFF) {
+        return Value(first);
+    }
+
+    int cp = ((first - 0xD800) * 1024) + (second - 0xDC00) + 0x10000;
+    return Value(cp);
+}
+
+static Value builtinStringCharAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, charAt);
+
+    int64_t position = 0;
+    if (argc > 0) {
+        position = argv[0].toInteger(state);
+    }
+
+    const auto& accessData = str->bufferAccessData();
+
+    if (LIKELY(0 <= position && position < (int64_t)accessData.length)) {
+        char16_t c;
+        if (accessData.has8BitContent) {
+            c = ((LChar*)accessData.buffer)[position];
+        } else {
+            c = ((char16_t*)accessData.buffer)[position];
+        }
+        if (LIKELY(c < ESCARGOT_ASCII_TABLE_MAX)) {
+            return state.context()->staticStrings().asciiTable[c].string();
+        } else {
+            return String::fromCharCode(c);
+        }
+    } else {
+        return String::emptyString;
+    }
+}
+
+static Value builtinStringFromCharCode(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (argc == 1) {
+        char16_t c = argv[0].toUint32(state) & 0xFFFF;
+        if (c < ESCARGOT_ASCII_TABLE_MAX)
+            return state.context()->staticStrings().asciiTable[c].string();
+        return String::fromCharCode(c);
+    }
+
+    StringBuilder builder;
+    for (size_t i = 0; i < argc; i++) {
+        builder.appendChar((char16_t)argv[i].toUint32(state));
+    }
+    return builder.finalize(&state);
+}
+
+static Value builtinStringFromCodePoint(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    StringBuilder builder;
+    for (size_t nextIndex = 0; nextIndex < argc; nextIndex++) {
+        Value next = argv[nextIndex];
+        double nextCP = next.toNumber(state);
+        double toIntegerNexCP = next.toInteger(state);
+
+        if (nextCP != toIntegerNexCP || nextCP < 0 || nextCP > 0x10FFFF) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid code point");
+        }
+
+        uint32_t cp = (uint32_t)nextCP;
+
+        if (cp <= 65535) {
+            builder.appendChar((char16_t)cp);
+        } else {
+            char16_t cu1 = floor((cp - 65536) / 1024) + 0xD800;
+            char16_t cu2 = ((cp - 65536) % 1024) + 0xDC00;
+
+            builder.appendChar(cu1);
+            builder.appendChar(cu2);
+        }
+    }
+
+    return builder.finalize(&state);
+}
+
+static Value builtinStringConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, concat);
+    for (size_t i = 0; i < argc; i++) {
+        String* appendStr = argv[i].toString(state);
+        str = RopeString::createRopeString(str, appendStr, &state);
+    }
+    return Value(str);
+}
+
+static Value builtinStringSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, slice);
+    size_t len = str->length();
+    double start = argv[0].toInteger(state);
+    double end = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
+    int from = (start < 0) ? std::max(len + start, 0.0) : std::min(start, (double)len);
+    int to = (end < 0) ? std::max(len + end, 0.0) : std::min(end, (double)len);
+    int span = std::max(to - from, 0);
+    return str->substring(from, from + span);
+}
+
+#if defined(ENABLE_ICU)
+static String* stringToLocaleConvertCase(ExecutionState& state, String* str, String* locale, bool isUpper)
+{
+    int32_t len = str->length();
+    char16_t* src = ALLOCA(len * 2, char16_t, state);
+    if (str->has8BitContent()) {
+        const LChar* buf = str->characters8();
+        for (int32_t i = 0; i < len; i++) {
+            src[i] = buf[i];
+        }
+    } else {
+        memcpy(src, str->characters16(), len * 2);
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t dest_length = len * 3;
+    char16_t* dest = ALLOCA(dest_length * 2, char16_t, state);
+    if (isUpper) {
+        dest_length = u_strToUpper(dest, dest_length, src, len, (const char*)locale->characters8(), &status);
+    } else {
+        dest_length = u_strToLower(dest, dest_length, src, len, (const char*)locale->characters8(), &status);
+    }
+
+    ASSERT(status != U_BUFFER_OVERFLOW_ERROR);
+    ASSERT(U_SUCCESS(status));
+    return new UTF16String(dest, dest_length);
+}
+#endif
+
+static Value builtinStringToLowerCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLowerCase);
+    if (str->has8BitContent()) {
+        Latin1StringData newStr;
+        size_t len = str->length();
+        newStr.resizeWithUninitializedValues(len);
+        const LChar* buf = str->characters8();
+        for (size_t i = 0; i < len; i++) {
+#if defined(ENABLE_ICU)
+            char32_t u2 = u_tolower(buf[i]);
+#else
+            char32_t u2 = tolower(buf[i]);
+#endif
+            ASSERT(u2 < 256);
+            newStr[i] = u2;
+        }
+        return new Latin1String(std::move(newStr));
+    }
+
+#if defined(ENABLE_ICU)
+    return stringToLocaleConvertCase(state, str, String::emptyString, false);
+#else
+    size_t len = str->length();
+    UTF16StringData newStr;
+    if (str->has8BitContent()) {
+        const LChar* buf = str->characters8();
+        newStr.resizeWithUninitializedValues(len);
+        for (size_t i = 0; i < len; i++) {
+            newStr[i] = buf[i];
+        }
+    } else {
+        newStr = UTF16StringData(str->characters16(), len);
+    }
+    char16_t* buf = newStr.data();
+    for (size_t i = 0; i < len;) {
+        char32_t c;
+        size_t iBefore = i;
+        U16_NEXT(buf, i, len, c);
+
+        c = tolower(c);
+        if (c <= 0x10000) {
+            char16_t c2 = (char16_t)c;
+            buf[iBefore] = c2;
+        } else {
+            buf[iBefore] = (char16_t)(0xD800 + ((c - 0x10000) >> 10));
+            buf[iBefore + 1] = (char16_t)(0xDC00 + ((c - 0x10000) & 1023));
+        }
+    }
+    return new UTF16String(std::move(newStr));
+#endif
+}
+
+static Value builtinStringToUpperCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, toUpperCase);
+    if (str->has8BitContent()) {
+        Latin1StringData newStr;
+        size_t len = str->length();
+        newStr.resizeWithUninitializedValues(len);
+
+        bool fitTo8Bit = true;
+        size_t sharpSCount = 0;
+        const LChar* buf = str->characters8();
+        for (size_t i = 0; i < len; i++) {
+            LChar ch = buf[i];
+            // U+00B5 and U+00FF are mapped to a character beyond U+00FF
+            if (UNLIKELY(ch == 0xB5 || ch == 0xFF)) {
+                fitTo8Bit = false;
+                break;
+            }
+            // Lower case sharp-S converts to "SS" (two characters)
+            if (UNLIKELY(ch == 0xDF)) {
+                sharpSCount++;
+                continue;
+            }
+#if defined(ENABLE_ICU)
+            char32_t u2 = u_toupper(ch);
+#else
+            char32_t u2 = toupper(ch);
+#endif
+            ASSERT(u2 < 256);
+            newStr[i] = u2;
+        }
+        if (fitTo8Bit) {
+            if (UNLIKELY(sharpSCount > 0)) {
+                Latin1StringData newStr2;
+                newStr2.resizeWithUninitializedValues(len + sharpSCount);
+                size_t destIndex = 0;
+                for (size_t i = 0; i < len; i++) {
+                    LChar ch = buf[i];
+                    if (ch != 0xDF) {
+                        newStr2[destIndex++] = newStr[i];
+                    } else {
+                        newStr2[destIndex++] = 'S';
+                        newStr2[destIndex++] = 'S';
+                    }
+                }
+                ASSERT(destIndex == len + sharpSCount);
+                return new Latin1String(std::move(newStr2));
+            }
+            return new Latin1String(std::move(newStr));
+        }
+    }
+
+#if defined(ENABLE_ICU)
+    return stringToLocaleConvertCase(state, str, String::emptyString, true);
+#else
+    size_t len = str->length();
+    UTF16StringData newStr;
+    if (str->has8BitContent()) {
+        const LChar* buf = str->characters8();
+        newStr.resizeWithUninitializedValues(len);
+        for (size_t i = 0; i < len; i++) {
+            newStr[i] = buf[i];
+        }
+    } else
+        newStr = UTF16StringData(str->characters16(), len);
+    char16_t* buf = newStr.data();
+    for (size_t i = 0; i < len;) {
+        char32_t c;
+        size_t iBefore = i;
+        U16_NEXT(buf, i, len, c);
+
+        c = toupper(c);
+        if (c <= 0x10000) {
+            char16_t c2 = (char16_t)c;
+            buf[iBefore] = c2;
+        } else {
+            buf[iBefore] = (char16_t)(0xD800 + ((c - 0x10000) >> 10));
+            buf[iBefore + 1] = (char16_t)(0xDC00 + ((c - 0x10000) & 1023));
+        }
+    }
+    return new UTF16String(std::move(newStr));
+#endif
+}
+
+static Value builtinStringToLocaleLowerCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLocaleLowerCase);
+    Value locales = argc > 0 ? argv[0] : Value();
+    String* locale = Intl::getLocaleForStringLocaleConvertCase(state, locales);
+    if (str->has8BitContent() && locale->length() == 0) {
+        return builtinStringToLowerCase(state, thisValue, argc, argv, newTarget);
+    } else {
+        return stringToLocaleConvertCase(state, str, locale, false);
+    }
+#else
+    return builtinStringToLowerCase(state, thisValue, argc, argv, newTarget);
+#endif
+}
+
+static Value builtinStringToLocaleUpperCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLocaleUpperCase);
+    Value locales = argc > 0 ? argv[0] : Value();
+    String* locale = Intl::getLocaleForStringLocaleConvertCase(state, locales);
+    if (str->has8BitContent() && locale->length() == 0) {
+        return builtinStringToUpperCase(state, thisValue, argc, argv, newTarget);
+    } else {
+        return stringToLocaleConvertCase(state, str, locale, true);
+    }
+#else
+    return builtinStringToUpperCase(state, thisValue, argc, argv, newTarget);
+#endif
+}
+
+static Value builtinStringTrim(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let S be this value.
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, trim);
+    // Return ? TrimString(S, "start+end").
+    return str->trim(String::TrimBoth);
+}
+
+static Value builtinStringTrimStart(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let S be this value.
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, trimStart);
+    // Return ? TrimString(S, "start").
+    return str->trim(String::TrimStart);
+}
+
+static Value builtinStringTrimEnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let S be this value.
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, trimEnd);
+    // Return ? TrimString(S, "end").
+    return str->trim(String::TrimEnd);
+}
+
+static Value builtinStringValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isString()) {
+        return Value(thisValue);
+    } else if (thisValue.isObject() && thisValue.asObject()->isStringObject()) {
+        return Value(thisValue.asPointerValue()->asStringObject()->primitiveValue());
+    }
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotString);
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static Value builtinStringStartsWith(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, startsWith);
+    Value searchString = argv[0];
+    // Let isRegExp be ? IsRegExp(searchString).
+    // If isRegExp is true, throw a TypeError exception.
+
+    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with startsWith");
+    }
+    // Let searchStr be ? ToString(searchString).
+    String* searchStr = searchString.toString(state);
+    // Let pos be ? ToInteger(position). (If position is undefined, this step produces the value 0.)
+    double pos = 0;
+    if (argc >= 2) {
+        pos = argv[1].toInteger(state);
+    }
+
+    // Let len be the number of elements in S.
+    double len = S->length();
+    // Let start be min(max(pos, 0), len).
+    double start = std::min(std::max(pos, 0.0), len);
+    // Let searchLength be the number of elements in searchStr.
+    double searchLength = searchStr->length();
+    // If searchLength+start is greater than len, return false.
+    if (searchLength + start > len) {
+        return Value(false);
+    }
+    // If the sequence of elements of S starting at start of length searchLength is the same as the full element sequence of searchStr, return true.
+    // Otherwise, return false.
+    const auto& srcData = S->bufferAccessData();
+    const auto& src2Data = searchStr->bufferAccessData();
+
+    for (size_t i = 0; i < src2Data.length; i++) {
+        if (srcData.charAt(i + start) != src2Data.charAt(i)) {
+            return Value(false);
+        }
+    }
+
+    return Value(true);
+}
+
+static Value builtinStringEndsWith(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, endsWith);
+    Value searchString = argv[0];
+    // Let isRegExp be ? IsRegExp(searchString).
+    // If isRegExp is true, throw a TypeError exception.
+    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with endsWith");
+    }
+    // Let len be the number of elements in S.
+    double len = S->length();
+
+    // Let searchStr be ? ToString(searchString).
+    String* searchStr = searchString.toString(state);
+    // If endPosition is undefined, let pos be len, else let pos be ? ToInteger(endPosition).
+    double pos = 0;
+    if (argc >= 2 && !argv[1].isUndefined()) {
+        pos = argv[1].toInteger(state);
+    } else {
+        pos = len;
+    }
+
+    // Let end be min(max(pos, 0), len).
+    double end = std::min(std::max(pos, 0.0), len);
+    // Let searchLength be the number of elements in searchStr.
+    double searchLength = searchStr->length();
+    // Let start be end - searchLength.
+    double start = end - searchLength;
+    // If start is less than 0, return false.
+    if (start < 0) {
+        return Value(false);
+    }
+    // If the sequence of elements of S starting at start of length searchLength is the same as the full element sequence of searchStr, return true.
+    const auto& srcData = S->bufferAccessData();
+    const auto& src2Data = searchStr->bufferAccessData();
+    for (size_t i = 0; i < searchLength; i++) {
+        if (srcData.charAt(i + start) != src2Data.charAt(i)) {
+            return Value(false);
+        }
+    }
+
+    return Value(true);
+}
+
+// ( template, ...substitutions )
+static Value builtinStringRaw(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value argTemplate = argv[0];
+    // Let substitutions be a List consisting of all of the arguments passed to this function, starting with the second argument. If fewer than two arguments were passed, the List is empty.
+    // Let numberOfSubstitutions be the number of elements in substitutions.
+    size_t numberOfSubstitutions;
+    if (argc < 2) {
+        numberOfSubstitutions = 0;
+    } else {
+        numberOfSubstitutions = argc - 1;
+    }
+
+    // Let cooked be ? ToObject(template).
+    Object* cooked = argTemplate.toObject(state);
+    // Let raw be ? ToObject(? Get(cooked, "raw")).
+    Object* raw = cooked->get(state, ObjectPropertyName(state.context()->staticStrings().raw)).value(state, cooked).toObject(state);
+    // Let literalSegments be ? ToLength(? Get(raw, "length")).
+    double literalSegments = raw->length(state);
+    // If literalSegments ≤ 0, return the empty string.
+    if (literalSegments <= 0) {
+        return String::emptyString;
+    }
+    // Let stringElements be a new empty List.
+    StringBuilder stringElements;
+    // Let nextIndex be 0.
+    size_t nextIndex = 0;
+    // Repeat
+    while (true) {
+        // Let nextKey be ! ToString(nextIndex).
+        // Let nextSeg be ? ToString(? Get(raw, nextKey)).
+        String* nextSeg = raw->get(state, ObjectPropertyName(state, Value(nextIndex))).value(state, raw).toString(state);
+        // Append in order the code unit elements of nextSeg to the end of stringElements.
+        for (size_t i = 0; i < nextSeg->length(); i++) {
+            stringElements.appendChar(nextSeg->charAt(i));
+        }
+        // If nextIndex + 1 = literalSegments, then
+        if (nextIndex + 1 == literalSegments) {
+            // Return the String value whose code units are, in order, the elements in the List stringElements. If stringElements has no elements, the empty string is returned.
+            return stringElements.finalize(&state);
+        }
+        Value next;
+        // If nextIndex < numberOfSubstitutions, let next be substitutions[nextIndex].
+        if (nextIndex < numberOfSubstitutions) {
+            next = argv[nextIndex + 1];
+        } else {
+            // Else, let next be the empty String.
+            next = String::emptyString;
+        }
+        // Let nextSub be ? ToString(next).
+        String* nextSub = next.toString(state);
+        // Append in order the code unit elements of nextSub to the end of stringElements.
+        stringElements.appendString(nextSub);
+        // Let nextIndex be nextIndex + 1.
+        nextIndex++;
+    }
+}
+
+// https://www.ecma-international.org/ecma-262/8.0/#sec-string.prototype.padstart
+// 21.1.3.14String.prototype.padStart( maxLength [ , fillString ] )
+static Value builtinStringPadStart(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, padStart);
+
+    // Let intMaxLength be ? ToLength(maxLength).
+    // Let stringLength be the number of elements in S.
+    uint64_t intMaxLength = 0;
+    if (argc >= 1) {
+        intMaxLength = argv[0].toLength(state);
+    }
+    uint64_t stringLength = S->length();
+
+    // If intMaxLength is not greater than stringLength, return S.
+    if (intMaxLength <= stringLength) {
+        return S;
+    }
+
+    // If fillString is undefined, let filler be a String consisting solely of the code unit 0x0020 (SPACE).
+    // Else, let filler be ? ToString(fillString).
+    String* filler;
+    if (argc >= 2 && (!argv[1].isUndefined())) {
+        filler = argv[1].toString(state);
+    } else {
+        filler = state.context()->staticStrings().asciiTable[0x20].string();
+    }
+
+    // If filler is the empty String, return S.
+    if (filler->length() == 0) {
+        return S;
+    }
+
+    // Let fillLen be intMaxLength - stringLength.
+    uint64_t fillLen = intMaxLength - stringLength;
+
+    // Let truncatedStringFiller be a new String value consisting of repeated concatenations of filler truncated to length fillLen.
+    StringBuilder sb;
+    while (sb.contentLength() < fillLen) {
+        sb.appendString(filler);
+    }
+
+    // Build the string, than truncate the characters over fillLen
+    String* truncatedStringFiller = sb.finalize(&state);
+    truncatedStringFiller = truncatedStringFiller->substring(0, fillLen);
+
+    // Return a new String value computed by the concatenation of truncatedStringFiller and S.
+    sb.appendString(truncatedStringFiller);
+    sb.appendString(S);
+    return sb.finalize(&state);
+}
+
+// https://www.ecma-international.org/ecma-262/8.0/#sec-string.prototype.padend
+// 21.1.3.13String.prototype.padEnd( maxLength [ , fillString ] )
+static Value builtinStringPadEnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, padStart);
+
+    // Let intMaxLength be ? ToLength(maxLength).
+    // Let stringLength be the number of elements in S.
+    uint64_t intMaxLength = 0;
+    if (argc >= 1) {
+        intMaxLength = argv[0].toLength(state);
+    }
+    uint64_t stringLength = S->length();
+
+    // If intMaxLength is not greater than stringLength, return S.
+    if (intMaxLength <= stringLength) {
+        return S;
+    }
+
+    // If fillString is undefined, let filler be a String consisting solely of the code unit 0x0020 (SPACE).
+    // Else, let filler be ? ToString(fillString).
+    String* filler;
+    if (argc >= 2 && (!argv[1].isUndefined())) {
+        filler = argv[1].toString(state);
+    } else {
+        filler = state.context()->staticStrings().asciiTable[0x20].string();
+    }
+
+    // If filler is the empty String, return S.
+    if (filler->length() == 0) {
+        return S;
+    }
+
+    // Let fillLen be intMaxLength - stringLength.
+    uint64_t fillLen = intMaxLength - stringLength;
+
+    // Let truncatedStringFiller be a new String value consisting of repeated concatenations of filler truncated to length fillLen.
+    StringBuilder sb;
+    while (sb.contentLength() < fillLen) {
+        sb.appendString(filler);
+    }
+
+    // Build the string, than truncate the characters over fillLen
+    String* truncatedStringFiller = sb.finalize(&state);
+    truncatedStringFiller = truncatedStringFiller->substring(0, fillLen);
+
+    // Return a new String value computed by the concatenation of S and truncatedStringFiller.
+    sb.appendString(S);
+    sb.appendString(truncatedStringFiller);
+    return sb.finalize(&state);
+}
+
+// http://www.ecma-international.org/ecma-262/6.0/#sec-createhtml
+// Runtime Semantics: CreateHTML ( string, tag, attribute, value )
+static String* createHTML(ExecutionState& state, Value string, String* tag, String* attribute, Value value, AtomicString methodName)
+{
+    // Let str be RequireObjectCoercible(string).
+    // Let S be ToString(str).
+    // ReturnIfAbrupt(S).
+    if (string.isUndefinedOrNull()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, methodName.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
+    }
+    String* S = string.toString(state);
+
+    // Let p1 be the String value that is the concatenation of "<" and tag.
+    StringBuilder sb;
+    sb.appendChar('<');
+    sb.appendString(tag);
+    String* p1 = sb.finalize(&state);
+    // If attribute is not the empty String, then
+    if (attribute->length()) {
+        // Let V be ToString(value).
+        String* V = value.toString(state);
+        // ReturnIfAbrupt(V).
+        // Let escapedV be the String value that is the same as V except that each occurrence of the code unit 0x0022 (QUOTATION MARK) in V has been replaced with the six code unit sequence "&quot;".
+        StringBuilder sb;
+        for (size_t i = 0; i < V->length(); i++) {
+            char16_t ch = V->charAt(i);
+            if (ch == 0x22) {
+                sb.appendString("&quot;");
+            } else {
+                sb.appendChar(ch);
+            }
+        }
+        String* escapedV = sb.finalize(&state);
+
+        // Let p1 be the String value that is the concatenation of the following String values:
+        // The String value of p1
+        // Code unit 0x0020 (SPACE)
+        // The String value of attribute
+        // Code unit 0x003D (EQUALS SIGN)
+        // Code unit 0x0022 (QUOTATION MARK)
+        // The String value of escapedV
+        // Code unit 0x0022 (QUOTATION MARK)
+        sb.appendString(p1);
+        sb.appendChar((char)0x20);
+        sb.appendString(attribute);
+        sb.appendChar((char)0x3d);
+        sb.appendChar((char)0x22);
+        sb.appendString(escapedV);
+        sb.appendChar((char)0x22);
+        p1 = sb.finalize(&state);
+    }
+    // Let p2 be the String value that is the concatenation of p1 and ">".
+    // Let p3 be the String value that is the concatenation of p2 and S.
+    // Let p4 be the String value that is the concatenation of p3, "</", tag, and ">".
+    // Return p4.
+    sb.appendString(p1);
+    sb.appendChar('>');
+    sb.appendString(S);
+    sb.appendString("</");
+    sb.appendString(tag);
+    sb.appendChar('>');
+    return sb.finalize(&state);
+}
+
+// http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-string.prototype-object
+
+static Value builtinStringSubstr(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, substr);
+    if (argc < 1) {
+        return str;
+    }
+    double intStart = argv[0].toInteger(state);
+    double end;
+    if (argc > 1) {
+        if (argv[1].isUndefined()) {
+            end = std::numeric_limits<double>::infinity();
+        } else
+            end = argv[1].toInteger(state);
+    } else {
+        end = std::numeric_limits<double>::infinity();
+    }
+    double size = str->length();
+    if (intStart < 0)
+        intStart = std::max(size + intStart, 0.0);
+    double resultLength = std::min(std::max(end, 0.0), size - intStart);
+    if (resultLength <= 0)
+        return String::emptyString;
+
+    return str->substring(intStart, intStart + resultLength);
+}
+
+static Value builtinStringAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_STRING(str, String, substr);
+    size_t len = str->length();
+    double relativeStart = argv[0].toInteger(state);
+    if (relativeStart < 0) {
+        relativeStart = len + relativeStart;
+    }
+    if (relativeStart < 0 || relativeStart >= len) {
+        return Value();
+    }
+    return String::fromCharCode(str->charAt(relativeStart));
+}
+
+#define DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fnName, P0, P1, P2)                                                                    \
+    static Value builtinString##fnName(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+    {                                                                                                                                 \
+        return createHTML(state, thisValue, P0, P1, P2, state.context()->staticStrings().fnName);                                     \
+    }
+
+// String.prototype.anchor (name)
+// Return CreateHTML(S, "a", "name", name).
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(anchor, state.context()->staticStrings().asciiTable[(size_t)'a'].string(), state.context()->staticStrings().name.string(), argv[0])
+// String.prototype.big ()
+// Return CreateHTML(S, "big", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(big, state.context()->staticStrings().big.string(), String::emptyString, String::emptyString)
+// String.prototype.blink ()
+// Return CreateHTML(S, "blink", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(blink, state.context()->staticStrings().blink.string(), String::emptyString, String::emptyString)
+// String.prototype.bold ()
+// Return CreateHTML(S, "b", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(bold, state.context()->staticStrings().asciiTable[(size_t)'b'].string(), String::emptyString, String::emptyString)
+// String.prototype.fixed ()
+// Return CreateHTML(S, "tt", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fixed, String::fromASCII("tt"), String::emptyString, String::emptyString)
+// String.prototype.fontcolor (color)
+// Return CreateHTML(S, "font", "color", color).
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontcolor, String::fromASCII("font"), String::fromASCII("color"), argv[0])
+// String.prototype.fontsize (size)
+// Return CreateHTML(S, "font", "size", size).
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontsize, String::fromASCII("font"), state.context()->staticStrings().size.string(), argv[0])
+// String.prototype.italics ()
+// Return CreateHTML(S, "i", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(italics, state.context()->staticStrings().asciiTable[(size_t)'i'].string(), String::emptyString, String::emptyString)
+// String.prototype.link (url)
+// Return CreateHTML(S, "a", "href", url).
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(link, state.context()->staticStrings().asciiTable[(size_t)'a'].string(), String::fromASCII("href"), argv[0])
+// String.prototype.small ()
+// Return CreateHTML(S, "small", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(small, state.context()->staticStrings().small.string(), String::emptyString, String::emptyString)
+// String.prototype.strike ()
+// Return CreateHTML(S, "strike", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(strike, state.context()->staticStrings().strike.string(), String::emptyString, String::emptyString)
+// String.prototype.sub ()
+// Return CreateHTML(S, "sub", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sub, state.context()->staticStrings().sub.string(), String::emptyString, String::emptyString)
+// String.prototype.sup ()
+// Return CreateHTML(S, "sup", "", "").
+DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sup, state.context()->staticStrings().sup.string(), String::emptyString, String::emptyString)
+
+#undef DEFINE_STRING_ADDITIONAL_HTML_FUNCTION
+
+static Value builtinStringIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, includes);
+    // Let isRegExp be ? IsRegExp(searchString).
+    // If isRegExp is true, throw a TypeError exception.
+    Value searchString = argv[0];
+    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with includes");
+    }
+
+    // Let searchStr be ? ToString(searchString).
+    String* searchStr = searchString.toString(state);
+
+    // Let pos be ? ToInteger(position). (If position is undefined, this step produces the value 0.)
+    double pos = 0;
+    if (argc >= 2) {
+        pos = argv[1].toInteger(state);
+    }
+
+    // Let len be the number of elements in S.
+    double len = S->length();
+
+    // Let start be min(max(pos, 0), len).
+    double start = std::min(std::max(pos, 0.0), len);
+    // Let searchLen be the number of elements in searchStr.
+    // If there exists any integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k+j of S is the same as the code unit at index j of searchStr, return true; but if there is no such integer k, return false.
+    auto ret = S->find(searchStr, start);
+    if (ret == SIZE_MAX) {
+        return Value(false);
+    }
+    return Value(true);
+}
+
+static Value builtinStringIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isStringIteratorObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().StringIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    StringIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asStringIteratorObject();
+    return iter->next(state);
+}
+
+static Value builtinStringIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? RequireObjectCoercible(this value).
+    // Let S be ? ToString(O).
+    RESOLVE_THIS_BINDING_TO_STRING(S, String, iterator);
+    // Return CreateStringIterator(S).
+    return new StringIteratorObject(state, S);
+}
+
+void GlobalObject::installString(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    m_string = new NativeFunctionObject(state, NativeFunctionInfo(strings->String, builtinStringConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_string->setGlobalIntrinsicObject(state);
+
+    m_stringPrototype = new StringObject(state, m_objectPrototype, String::emptyString);
+    m_stringPrototype->setGlobalIntrinsicObject(state, true);
+    m_string->setFunctionPrototype(state, m_stringPrototype);
+
+    m_stringPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinStringToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.1.3.4 String.prototype.concat
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->concat),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->concat, builtinStringConcat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.1.3.8 String.prototype.indexOf
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->indexOf),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->indexOf, builtinStringIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->lastIndexOf),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lastIndexOf, builtinStringLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->localeCompare),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->localeCompare, builtinStringLocaleCompare, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.1.3.16 String.prototype.slice
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinStringSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.1.3.19 String.prototype.substring
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->substring),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->substring, builtinStringSubstring, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->substr),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->substr, builtinStringSubstr, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->match),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->match, builtinStringMatch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->matchAll),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->matchAll, builtinStringMatchAll, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+#if defined(ENABLE_ICU)
+    // The length property of the normalize method is 0.
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->normalize),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->normalize, builtinStringNormalize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+#endif // ENABLE_ICU
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->repeat),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->repeat, builtinStringRepeat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->replace),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->replace, builtinStringReplace, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->replaceAll),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->replaceAll, builtinStringReplaceAll, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->search),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->search, builtinStringSearch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->split),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->split, builtinStringSplit, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->charCodeAt),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->charCodeAt, builtinStringCharCodeAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->codePointAt),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->codePointAt, builtinStringCodePointAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->charAt),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->charAt, builtinStringCharAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLowerCase),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLowerCase, builtinStringToLowerCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toUpperCase),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toUpperCase, builtinStringToUpperCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleLowerCase),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleLowerCase, builtinStringToLocaleLowerCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleUpperCase),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleUpperCase, builtinStringToLocaleUpperCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trim),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->trim, builtinStringTrim, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->padStart),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->padStart, builtinStringPadStart, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->padEnd),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->padEnd, builtinStringPadEnd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    FunctionObject* trimStart = new NativeFunctionObject(state, NativeFunctionInfo(strings->trimStart, builtinStringTrimStart, 0, NativeFunctionInfo::Strict));
+    FunctionObject* trimEnd = new NativeFunctionObject(state, NativeFunctionInfo(strings->trimEnd, builtinStringTrimEnd, 0, NativeFunctionInfo::Strict));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimStart),
+                                                        ObjectPropertyDescriptor(trimStart, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimEnd),
+                                                        ObjectPropertyDescriptor(trimEnd, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimRight),
+                                                        ObjectPropertyDescriptor(trimEnd, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimLeft),
+                                                        ObjectPropertyDescriptor(trimStart, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // $21.1.3.26 String.prototype.valueOf
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinStringValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // ES6 builtins
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->startsWith),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->startsWith, builtinStringStartsWith, 1, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->endsWith),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->endsWith, builtinStringEndsWith, 1, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->includes),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->includes, builtinStringIncludes, 1, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinStringIterator, 0, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->at),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->at, builtinStringAt, 1, NativeFunctionInfo::Strict)),
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+#define DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fnName, argLength)                                                                                                                                                    \
+    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fnName),                                                                                                                  \
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fnName, builtinString##fnName, argLength, NativeFunctionInfo::Strict)), \
+                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // String.prototype.anchor (name)
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(anchor, 1)
+    // String.prototype.big ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(big, 0)
+    // String.prototype.blink ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(blink, 0)
+    // String.prototype.bold ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(bold, 0)
+    // String.prototype.fixed ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fixed, 0)
+    // String.prototype.fontcolor (color)
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontcolor, 1)
+    // String.prototype.fontsize (size)
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontsize, 1)
+    // String.prototype.italics ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(italics, 0)
+    // String.prototype.link (url)
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(link, 1)
+    // String.prototype.small ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(small, 0)
+    // String.prototype.strike ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(strike, 0)
+    // String.prototype.sub ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sub, 0)
+    // String.prototype.sup ()
+    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sup, 0)
+
+#undef DEFINE_STRING_ADDITIONAL_HTML_FUNCTION
+
+    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fromCharCode),
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fromCharCode, builtinStringFromCharCode, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fromCodePoint),
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fromCodePoint, builtinStringFromCodePoint, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->raw),
+                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->raw, builtinStringRaw, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_string->setFunctionPrototype(state, m_stringPrototype);
+
+    m_stringIteratorPrototype = new Object(state, m_iteratorPrototype);
+    m_stringIteratorPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_stringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
+                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinStringIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_stringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
+                                                                ObjectPropertyDescriptor(Value(String::fromASCII("String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(strings->String),
+                      ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinSymbol.cpp
new file mode 100644 (file)
index 0000000..5e848f6
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/SymbolObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinSymbolConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is not undefined, throw a TypeError exception.
+    if (newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "illegal constructor Symbol");
+    }
+    Optional<String*> descString = nullptr;
+    // If description is undefined, let descString be undefined.
+    if (!(argc == 0 || argv[0].isUndefined())) {
+        // Else, let descString be ? ToString(description).
+        descString = argv[0].toString(state);
+    }
+    // Return a new unique Symbol value whose [[Description]] value is descString.
+    return new Symbol(descString);
+}
+
+#define RESOLVE_THIS_BINDING_TO_SYMBOL(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                           \
+    Symbol* NAME = nullptr;                                                                                                                                                                                                                                  \
+    if (thisValue.isObject()) {                                                                                                                                                                                                                              \
+        if (!thisValue.asObject()->isSymbolObject()) {                                                                                                                                                                                                       \
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+        }                                                                                                                                                                                                                                                    \
+        NAME = thisValue.asObject()->asSymbolObject()->primitiveValue();                                                                                                                                                                                     \
+    } else if (thisValue.isSymbol()) {                                                                                                                                                                                                                       \
+        NAME = thisValue.asSymbol();                                                                                                                                                                                                                         \
+    } else {                                                                                                                                                                                                                                                 \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);     \
+    }
+
+static Value builtinSymbolToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, toString);
+    return S->symbolDescriptiveString();
+}
+
+static Value builtinSymbolValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, valueOf);
+    return Value(S);
+}
+
+static Value builtinSymbolToPrimitive(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, toPrimitive);
+    return Value(S);
+}
+
+static Value builtinSymbolFor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let stringKey be ? ToString(key).
+    String* stringKey = argv[0].toString(state);
+    return Symbol::fromGlobalSymbolRegistry(state.context()->vmInstance(), stringKey);
+}
+
+static Value builtinSymbolKeyFor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If Type(sym) is not Symbol, throw a TypeError exception.
+    if (!argv[0].isSymbol()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
+    }
+    Symbol* sym = argv[0].asSymbol();
+    // For each element e of the GlobalSymbolRegistry List (see 19.4.2.1),
+    auto& list = state.context()->vmInstance()->globalSymbolRegistry();
+    for (size_t i = 0; i < list.size(); i++) {
+        // If SameValue(e.[[Symbol]], sym) is true, return e.[[Key]].
+        if (list[i].symbol == sym) {
+            return list[i].key.value();
+        }
+    }
+    // Assert: GlobalSymbolRegistry does not currently contain an entry for sym.
+    // Return undefined.
+    return Value();
+}
+
+static Value builtinSymbolDescriptionGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (thisValue.isSymbol()) {
+        if (!thisValue.asSymbol()->description().hasValue()) {
+            return Value();
+        }
+
+        return thisValue.asSymbol()->description().value();
+
+    } else if (thisValue.isObject() && thisValue.asObject()->isSymbolObject()) {
+        if (!thisValue.asObject()->asSymbolObject()->primitiveValue()->description().hasValue()) {
+            return Value();
+        }
+
+        return thisValue.asObject()->asSymbolObject()->primitiveValue()->description().value();
+
+    } else {
+        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, "getter called on non-Symbol object");
+    }
+    return Value();
+}
+
+void GlobalObject::installSymbol(ExecutionState& state)
+{
+    m_symbol = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Symbol, builtinSymbolConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_symbol->setGlobalIntrinsicObject(state);
+
+    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringFor),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringFor, builtinSymbolFor, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keyFor),
+                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keyFor, builtinSymbolKeyFor, 1, NativeFunctionInfo::Strict)),
+                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbolPrototype = new Object(state);
+    m_symbolPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinSymbolToString, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
+                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinSymbolValueOf, 0, NativeFunctionInfo::Strict)),
+                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbolPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toPrimitive)),
+                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.toPrimitive]")), builtinSymbolToPrimitive, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_symbolPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                        ObjectPropertyDescriptor(state.context()->staticStrings().Symbol.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    {
+        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getDescription, builtinSymbolDescriptionGetter, 0, NativeFunctionInfo::Strict));
+        JSGetterSetter gs(getter, Value());
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().description), desc);
+    }
+
+
+#define DECLARE_GLOBAL_SYMBOLS(name) \
+    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().name), ObjectPropertyDescriptor(Value(state.context()->vmInstance()->globalSymbols().name), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
+    DEFINE_GLOBAL_SYMBOLS(DECLARE_GLOBAL_SYMBOLS);
+
+    m_symbol->setFunctionPrototype(state, m_symbolPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Symbol),
+                      ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinTypedArray.cpp
new file mode 100644 (file)
index 0000000..4b607e2
--- /dev/null
@@ -0,0 +1,1746 @@
+/*
+ * Copyright (c) 2017-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/Object.h"
+#include "runtime/TypedArrayObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+#define RESOLVE_THIS_BINDING_TO_TYPEDARRAY(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                   \
+    if (UNLIKELY(!thisValue.isObject() || !thisValue.asObject()->isTypedArrayObject())) {                                                                                                                                                                \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                    \
+    TypedArrayObject* NAME = thisValue.asPointerValue()->asTypedArrayObject();
+
+
+// https://www.ecma-international.org/ecma-262/10.0/#typedarray-create
+static Object* createTypedArray(ExecutionState& state, const Value& constructor, size_t argc, Value* argv)
+{
+    Object* newTypedArray = Object::construct(state, constructor, argc, argv).toObject(state);
+    TypedArrayObject::validateTypedArray(state, newTypedArray);
+
+    if (argc == 1 && argv[0].isNumber()) {
+        double arrayLength = newTypedArray->asTypedArrayObject()->arrayLength();
+        if (arrayLength < argv[0].asNumber()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "invalid TypedArray length");
+        }
+    }
+
+    return newTypedArray;
+}
+
+static Value getDefaultTypedArrayConstructor(ExecutionState& state, const TypedArrayType type)
+{
+    GlobalObject* glob = state.context()->globalObject();
+    switch (type) {
+    case TypedArrayType::Int8:
+        return glob->int8Array();
+    case TypedArrayType::Uint8:
+        return glob->uint8Array();
+    case TypedArrayType::Uint8Clamped:
+        return glob->uint8ClampedArray();
+    case TypedArrayType::Int16:
+        return glob->int16Array();
+    case TypedArrayType::Uint16:
+        return glob->uint16Array();
+    case TypedArrayType::Int32:
+        return glob->int32Array();
+    case TypedArrayType::Uint32:
+        return glob->uint32Array();
+    case TypedArrayType::Float32:
+        return glob->float32Array();
+    case TypedArrayType::Float64:
+        return glob->float64Array();
+    case TypedArrayType::BigInt64:
+        return glob->bigInt64Array();
+    case TypedArrayType::BigUint64:
+        return glob->bigUint64Array();
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    return Value();
+}
+
+static Value TypedArraySpeciesCreate(ExecutionState& state, TypedArrayObject* exemplar, size_t argc, Value* argumentList)
+{
+    // Let defaultConstructor be the intrinsic object listed in column one of Table 49 for the value of O’s [[TypedArrayName]] internal slot.
+    Value defaultConstructor = getDefaultTypedArrayConstructor(state, exemplar->typedArrayType());
+    // Let C be SpeciesConstructor(O, defaultConstructor).
+    Value C = exemplar->speciesConstructor(state, defaultConstructor);
+    Value A = Object::construct(state, C, argc, argumentList);
+    TypedArrayObject::validateTypedArray(state, A);
+    if (argc == 1 && argumentList[0].isNumber() && A.asObject()->asTypedArrayObject()->arrayLength() < argumentList->toNumber(state)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayLength);
+    }
+    return A;
+}
+
+static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::Not_Constructor);
+    return Value();
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.from
+static Value builtinTypedArrayFrom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value C = thisValue;
+    Value source = argv[0];
+
+    if (!C.isConstructor()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
+    }
+
+    Value mapfn;
+    if (argc > 1) {
+        mapfn = argv[1];
+    }
+    Value T;
+    if (argc > 2) {
+        T = argv[2];
+    }
+
+    bool mapping = false;
+    if (!mapfn.isUndefined()) {
+        if (!mapfn.isCallable()) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "mapfn is not callable");
+        }
+        mapping = true;
+    }
+
+    Value usingIterator = Object::getMethod(state, source, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
+    if (!usingIterator.isUndefined()) {
+        ValueVectorWithInlineStorage values = IteratorObject::iterableToList(state, source, usingIterator);
+        size_t len = values.size();
+        Value arg[1] = { Value(len) };
+        Object* targetObj = createTypedArray(state, C, 1, arg);
+
+        size_t k = 0;
+        while (k < len) {
+            Value mappedValue = values[k];
+            if (mapping) {
+                Value args[2] = { values[k], Value(k) };
+                mappedValue = Object::call(state, mapfn, T, 2, args);
+            }
+            targetObj->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
+            k++;
+        }
+
+        return targetObj;
+    }
+
+    Object* arrayLike = source.toObject(state);
+    size_t len = arrayLike->length(state);
+
+    Value arg[1] = { Value(len) };
+    Object* targetObj = createTypedArray(state, C, 1, arg);
+
+    size_t k = 0;
+    while (k < len) {
+        Value kValue = arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike);
+        Value mappedValue = kValue;
+        if (mapping) {
+            // Let mappedValue be Call(mapfn, T, «kValue, k»).
+            Value args[2] = { kValue, Value(k) };
+            mappedValue = Object::call(state, mapfn, T, 2, args);
+        }
+        // Let setStatus be Set(targetObj, Pk, mappedValue, true).
+        targetObj->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
+        k++;
+    }
+
+    return targetObj;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.of
+static Value builtinTypedArrayOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    size_t len = argc;
+    Value C = thisValue;
+    if (!C.isConstructor()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
+    }
+
+    Value arg[1] = { Value(len) };
+    Object* newObj = createTypedArray(state, C, 1, arg);
+
+    size_t k = 0;
+    while (k < len) {
+        Value kValue = argv[k];
+        newObj->setIndexedPropertyThrowsException(state, Value(k), kValue);
+        k++;
+    }
+    return newObj;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.buffer
+static Value builtinTypedArrayBufferGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getBuffer);
+    return buffer->buffer();
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.bytelength
+static Value builtinTypedArrayByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteLength);
+    if (buffer->buffer()->isDetachedBuffer()) {
+        return Value(0);
+    }
+    return Value(buffer->byteLength());
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.byteoffset
+static Value builtinTypedArrayByteOffsetGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteOffset);
+    if (buffer->buffer()->isDetachedBuffer()) {
+        return Value(0);
+    }
+    return Value(buffer->byteOffset());
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.length
+static Value builtinTypedArrayLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteOffset);
+    if (buffer->buffer()->isDetachedBuffer()) {
+        return Value(0);
+    }
+    return Value(buffer->arrayLength());
+}
+
+static void initializeTypedArrayFromTypedArray(ExecutionState& state, TypedArrayObject* obj, TypedArrayObject* srcArray)
+{
+    ArrayBuffer* srcData = srcArray->buffer();
+    srcData->throwTypeErrorIfDetached(state);
+
+    size_t elementLength = srcArray->arrayLength();
+    size_t srcElementSize = srcArray->elementSize();
+    size_t srcByteOffset = srcArray->byteOffset();
+    size_t elementSize = obj->elementSize();
+    uint64_t byteLength = elementSize * elementLength;
+
+    Value bufferConstructor;
+#if defined(ENABLE_THREADING)
+    if (srcData->isSharedArrayBufferObject())
+        // Let bufferConstructor be %ArrayBuffer%.
+        bufferConstructor = state.context()->globalObject()->arrayBuffer();
+    else
+#endif
+        // Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%).
+        bufferConstructor = srcData->speciesConstructor(state, state.context()->globalObject()->arrayBuffer());
+
+    ArrayBufferObject* data = nullptr;
+    if (obj->typedArrayType() == srcArray->typedArrayType()) {
+        // Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor).
+        data = ArrayBufferObject::cloneArrayBuffer(state, srcData, srcByteOffset, byteLength, bufferConstructor.asObject());
+    } else {
+        // Let data be AllocateArrayBuffer(bufferConstructor, byteLength).
+        data = ArrayBufferObject::allocateArrayBuffer(state, bufferConstructor.asObject(), byteLength);
+        // If IsDetachedBuffer(srcData) is true, throw a TypeError exception.
+        srcData->throwTypeErrorIfDetached(state);
+
+        // Let srcByteIndex be srcByteOffset.
+        size_t srcByteIndex = srcByteOffset;
+        // Let targetByteIndex be 0.
+        size_t targetByteIndex = 0;
+        // Let count be elementLength.
+        size_t count = elementLength;
+        // Repeat, while count > 0
+        while (count > 0) {
+            // Let value be GetValueFromBuffer(srcData, srcByteIndex, srcType).
+            Value value = srcData->getValueFromBuffer(state, srcByteIndex, srcArray->typedArrayType());
+            // Perform SetValueInBuffer(data, targetByteIndex, elementType, value).
+            data->setValueInBuffer(state, targetByteIndex, obj->typedArrayType(), value);
+            // Set srcByteIndex to srcByteIndex + srcElementSize.
+            srcByteIndex += srcElementSize;
+            // Set targetByteIndex to targetByteIndex + elementSize.
+            targetByteIndex += elementSize;
+            // Decrement count by 1.
+            count--;
+        }
+    }
+    // Set O’s [[ViewedArrayBuffer]] internal slot to data.
+    // Set O’s [[ByteLength]] internal slot to byteLength.
+    // Set O’s [[ByteOffset]] internal slot to 0.
+    // Set O’s [[ArrayLength]] internal slot to elementLength.
+    obj->setBuffer(data, 0, byteLength, elementLength);
+}
+
+static void initializeTypedArrayFromArrayBuffer(ExecutionState& state, TypedArrayObject* obj, ArrayBuffer* buffer, const Value& byteOffset, const Value& length)
+{
+    size_t elementSize = obj->elementSize();
+    uint64_t offset = byteOffset.toIndex(state);
+    if (offset == Value::InvalidIndexValue || offset % elementSize != 0) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+    }
+
+    uint64_t newLength = 0;
+    if (!length.isUndefined()) {
+        newLength = length.toIndex(state);
+        if (newLength == Value::InvalidIndexValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+        }
+    }
+
+    buffer->throwTypeErrorIfDetached(state);
+    size_t bufferByteLength = buffer->byteLength();
+
+    size_t newByteLength = 0;
+    if (length.isUndefined()) {
+        if ((bufferByteLength % elementSize != 0) || (bufferByteLength < offset)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+        }
+        newByteLength = bufferByteLength - offset;
+    } else {
+        newByteLength = newLength * elementSize;
+        if (offset + newByteLength > bufferByteLength) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
+        }
+    }
+
+    obj->setBuffer(buffer, offset, newByteLength, newByteLength / elementSize);
+}
+
+static void initializeTypedArrayFromList(ExecutionState& state, TypedArrayObject* obj, const ValueVectorWithInlineStorage& values)
+{
+    size_t len = values.size();
+
+    // Perform ? AllocateTypedArrayBuffer(O, len).
+    size_t elementSize = obj->elementSize();
+    uint64_t byteLength = len * elementSize;
+    ArrayBufferObject* buffer = ArrayBufferObject::allocateArrayBuffer(state, state.context()->globalObject()->arrayBuffer(), byteLength);
+    obj->setBuffer(buffer, 0, byteLength, len);
+
+    size_t k = 0;
+    while (k < len) {
+        // Perform ? Set(O, Pk, kValue, true).
+        obj->setIndexedPropertyThrowsException(state, Value(k), values[k]);
+        k++;
+    }
+}
+
+static void initializeTypedArrayFromArrayLike(ExecutionState& state, TypedArrayObject* obj, Object* arrayLike)
+{
+    size_t len = arrayLike->length(state);
+
+    // Perform ? AllocateTypedArrayBuffer(O, len).
+    size_t elementSize = obj->elementSize();
+    uint64_t byteLength = len * elementSize;
+    ArrayBufferObject* buffer = ArrayBufferObject::allocateArrayBuffer(state, state.context()->globalObject()->arrayBuffer(), byteLength);
+    obj->setBuffer(buffer, 0, byteLength, len);
+
+    size_t k = 0;
+    while (k < len) {
+        // Perform ? Set(O, Pk, kValue, true).
+        obj->setIndexedPropertyThrowsException(state, Value(k), arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike));
+        k++;
+    }
+}
+
+template <typename TA>
+static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // if NewTarget is undefined, throw a TypeError
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    if (argc == 0) {
+        // $22.2.4.1 TypedArray ()
+        return TA::allocateTypedArray(state, newTarget.value(), 0);
+    }
+
+    const Value& firstArg = argv[0];
+    if (!firstArg.isObject()) {
+        uint64_t elemlen = firstArg.toIndex(state);
+        if (elemlen == Value::InvalidIndexValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
+        }
+        return TA::allocateTypedArray(state, newTarget.value(), elemlen);
+    }
+
+    ASSERT(firstArg.isObject());
+    Object* argObj = firstArg.asObject();
+    TypedArrayObject* obj = TA::allocateTypedArray(state, newTarget.value());
+
+    if (argObj->isTypedArrayObject()) {
+        initializeTypedArrayFromTypedArray(state, obj, argObj->asTypedArrayObject());
+    } else if (argObj->isArrayBuffer()) {
+        Value byteOffset = (argc > 1) ? argv[1] : Value();
+        Value length = (argc > 2) ? argv[2] : Value();
+        initializeTypedArrayFromArrayBuffer(state, obj, argObj->asArrayBuffer(), byteOffset, length);
+    } else {
+        Value usingIterator = Object::getMethod(state, argObj, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
+        if (!usingIterator.isUndefined()) {
+            ValueVectorWithInlineStorage values = IteratorObject::iterableToList(state, argObj, usingIterator);
+            initializeTypedArrayFromList(state, obj, values);
+        } else {
+            initializeTypedArrayFromArrayLike(state, obj, argObj);
+        }
+    }
+
+    return obj;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.copywithin
+static Value builtinTypedArrayCopyWithin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
+
+    // Let len be O.[[ArrayLength]].
+    double len = O->arrayLength();
+
+    // Let relativeTarget be ToInteger(target).
+    double relativeTarget = argv[0].toInteger(state);
+    // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len).
+    double to = (relativeTarget < 0.0) ? std::max((len + relativeTarget), 0.0) : std::min(relativeTarget, len);
+
+    // Let relativeStart be ToInteger(start).
+    double relativeStart = argv[1].toInteger(state);
+    // If relativeStart < 0, let from be max((len + relativeStart),0); else let from be min(relativeStart, len).
+    double from = (relativeStart < 0.0) ? std::max((len + relativeStart), 0.0) : std::min(relativeStart, len);
+
+    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
+    double relativeEnd = (argc <= 2 || argv[2].isUndefined()) ? len : argv[2].toInteger(state);
+    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
+    double finalEnd = (relativeEnd < 0.0) ? std::max((len + relativeEnd), 0.0) : std::min(relativeEnd, len);
+
+    // Let count be min(final-from, len-to).
+    double count = std::min(finalEnd - from, len - to);
+    // If count > 0, then
+    if (count > 0) {
+        // Let buffer be O.[[ViewedArrayBuffer]].
+        ArrayBuffer* buffer = O->buffer();
+        // If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
+        buffer->throwTypeErrorIfDetached(state);
+        // Let typedArrayName be the String value of O.[[TypedArrayName]].
+        // Let elementSize be the Number value of the Element Size value specified in Table 59 for typedArrayName.
+        size_t elementSize = O->elementSize();
+        // Let byteOffset be O.[[ByteOffset]].
+        size_t byteOffset = O->byteOffset();
+        // Let toByteIndex be to × elementSize + byteOffset.
+        size_t toByteIndex = to * elementSize + byteOffset;
+        // Let fromByteIndex be from × elementSize + byteOffset.
+        size_t fromByteIndex = from * elementSize + byteOffset;
+        // Let countBytes be count × elementSize.
+        size_t countBytes = count * elementSize;
+
+        int8_t direction = 0;
+        // If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
+        if (fromByteIndex < toByteIndex && toByteIndex < fromByteIndex + countBytes) {
+            // Let direction be -1.
+            direction = -1;
+            // Set fromByteIndex to fromByteIndex + countBytes - 1.
+            fromByteIndex = fromByteIndex + countBytes - 1;
+            // Set toByteIndex to toByteIndex + countBytes - 1.
+            toByteIndex = toByteIndex + countBytes - 1;
+        } else {
+            // Let direction be 1.
+            direction = 1;
+        }
+
+        // Repeat, while countBytes > 0
+        while (countBytes > 0) {
+            // Let value be GetValueFromBuffer(buffer, fromByteIndex, "Uint8", true, "Unordered").
+            Value value = buffer->getValueFromBuffer(state, fromByteIndex, TypedArrayType::Uint8);
+            // Perform SetValueInBuffer(buffer, toByteIndex, "Uint8", value, true, "Unordered").
+            buffer->setValueInBuffer(state, toByteIndex, TypedArrayType::Uint8, value);
+            // Set fromByteIndex to fromByteIndex + direction.
+            fromByteIndex += direction;
+            // Set toByteIndex to toByteIndex + direction.
+            toByteIndex += direction;
+            // Decrease countBytes by 1.
+            countBytes--;
+        }
+    }
+
+    // return O.
+    return O;
+}
+
+static Value builtinTypedArrayIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // NOTE: Same algorithm as Array.prototype.indexOf
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, indexOf);
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Let lenValue be this object's [[ArrayLength]] internal slot.
+    // Let len be ToUint32(lenValue).
+    size_t len = O->asTypedArrayObject()->arrayLength();
+
+    // If len is 0, return -1.
+    if (len == 0) {
+        return Value(-1);
+    }
+
+    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
+    double n = 0;
+    if (argc > 1) {
+        n = argv[1].toInteger(state);
+    }
+
+    // If n ≥ len, return -1.
+    if (n >= len) {
+        return Value(-1);
+    }
+
+    double doubleK;
+    // If n ≥ 0, then
+    if (n >= 0) {
+        // Let k be n.
+        doubleK = (n == -0) ? 0 : n;
+    } else {
+        // Else, n<0
+        // Let k be len + n
+        doubleK = len + n;
+        // If k is less than 0, then let k be 0.
+        if (doubleK < 0) {
+            doubleK = 0;
+        }
+    }
+    size_t k = (size_t)doubleK;
+
+    // Repeat, while k<len
+    while (k < len) {
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
+        ObjectGetResult kPresent = O->getIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent.hasValue()) {
+            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
+            Value elementK = kPresent.value(state, O);
+
+            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
+            if (elementK.equalsTo(state, argv[0])) {
+                // If same is true, return k.
+                return Value(k);
+            }
+        }
+        // Increase k by 1.
+        k++;
+    }
+
+    // Return -1.
+    return Value(-1);
+}
+
+static Value builtinTypedArrayLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // NOTE: Same algorithm as Array.prototype.lastIndexOf
+    // Let O be the result of calling ToObject passing the this value as the argument.
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, lastIndexOf);
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Let lenValue be this object's [[ArrayLength]] internal slot.
+    // Let len be ToUint32(lenValue).
+    size_t len = O->asTypedArrayObject()->arrayLength();
+
+    // If len is 0, return -1.
+    if (len == 0) {
+        return Value(-1);
+    }
+
+    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
+    double n;
+    if (argc > 1) {
+        n = argv[1].toInteger(state);
+    } else {
+        n = len - 1;
+    }
+
+    // If n ≥ 0, then let k be min(n, len – 1).
+    double doubleK;
+    if (n >= 0) {
+        doubleK = (n == -0) ? 0 : std::min(n, len - 1.0);
+    } else {
+        // Else, n < 0
+        // Let k be len + n.
+        doubleK = len + n;
+    }
+
+    if (doubleK < 0) {
+        return Value(-1);
+    }
+    int64_t k = (int64_t)doubleK;
+
+    // Repeat, while k≥ 0
+    while (k >= 0) {
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
+        ObjectGetResult kPresent = O->getIndexedProperty(state, Value(k));
+        // If kPresent is true, then
+        if (kPresent.hasValue()) {
+            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
+            Value elementK = kPresent.value(state, O);
+
+            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
+            if (elementK.equalsTo(state, argv[0])) {
+                // If same is true, return k.
+                return Value(k);
+            }
+        } else {
+            int64_t result;
+            Object::nextIndexBackward(state, O, k, -1, result);
+            k = result;
+            continue;
+        }
+        // Decrease k by 1.
+        k--;
+    }
+
+    // Return -1.
+    return Value(-1);
+}
+
+static Value builtinTypedArrayIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ? ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, includes);
+    TypedArrayObject::validateTypedArray(state, O);
+
+    size_t len = O->asTypedArrayObject()->arrayLength();
+
+    // If len is 0, return false.
+    if (len == 0) {
+        return Value(false);
+    }
+
+    Value searchElement = argv[0];
+    // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
+    double n = argc >= 2 ? argv[1].toInteger(state) : 0;
+    if (n >= len) {
+        return Value(false);
+    }
+
+    double doubleK;
+    // If n ≥ 0, then
+    if (n >= 0) {
+        // Let k be n.
+        doubleK = n;
+    } else {
+        // Else n < 0,
+        // Let k be len + n.
+        doubleK = len + n;
+        // If k < 0, let k be 0.
+        if (doubleK < 0) {
+            doubleK = 0;
+        }
+    }
+    size_t k = (size_t)doubleK;
+
+    // Repeat, while k < len
+    while (k < len) {
+        // Let elementK be the result of ? Get(O, ! ToString(k)).
+        Value elementK = O->getIndexedProperty(state, Value(k)).value(state, O);
+        // If SameValueZero(searchElement, elementK) is true, return true.
+        if (elementK.equalsToByTheSameValueZeroAlgorithm(state, searchElement)) {
+            return Value(true);
+        }
+        // Increase k by 1.
+        k++;
+    }
+
+    // Return false.
+    return Value(false);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.set-overloaded-offset
+static Value builtinTypedArraySet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    if (!thisValue.isObject() || !thisValue.asObject()->isTypedArrayObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_ThisNotTypedArrayObject);
+    }
+
+    TypedArrayObject* target = thisValue.asObject()->asTypedArrayObject();
+
+    double targetOffset = 0;
+    if (argc > 1) {
+        targetOffset = argv[1].toInteger(state);
+    }
+    if (targetOffset < 0) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), "Start offset is negative");
+    }
+
+    auto typedArrayType = target->typedArrayType();
+    bool isBigIntArray = typedArrayType == TypedArrayType::BigInt64 || typedArrayType == TypedArrayType::BigUint64;
+
+    ArrayBuffer* targetBuffer = target->buffer();
+    targetBuffer->throwTypeErrorIfDetached(state);
+    size_t targetLength = target->arrayLength();
+    size_t targetElementSize = target->elementSize();
+    size_t targetByteOffset = target->byteOffset();
+
+    Object* src = argv[0].toObject(state);
+    if (!src->isTypedArrayObject()) {
+        // 22.2.3.23.1%TypedArray%.prototype.set ( array [ , offset ] )
+        size_t srcLength = src->length(state);
+        if (srcLength + targetOffset > targetLength) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_InvalidArrayLength);
+        }
+
+        size_t targetByteIndex = targetOffset * targetElementSize + targetByteOffset;
+        size_t k = 0;
+        size_t limit = targetByteIndex + targetElementSize * srcLength;
+        while (targetByteIndex < limit) {
+            Value value = src->get(state, ObjectPropertyName(state, Value(k))).value(state, src);
+            if (UNLIKELY(isBigIntArray)) {
+                value = value.toBigInt(state);
+            } else {
+                value = Value(value.toNumber(state));
+            }
+            targetBuffer->throwTypeErrorIfDetached(state);
+
+            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, "Unordered").
+            targetBuffer->setValueInBuffer(state, targetByteIndex, target->typedArrayType(), value);
+
+            k++;
+            targetByteIndex += targetElementSize;
+        }
+
+        return Value();
+    }
+
+    // 22.2.3.23.2%TypedArray%.prototype.set ( typedArray [ , offset ] )
+    ASSERT(src->isTypedArrayObject());
+    TypedArrayObject* srcTypedArray = src->asTypedArrayObject();
+    ArrayBuffer* srcBuffer = srcTypedArray->buffer();
+    srcBuffer->throwTypeErrorIfDetached(state);
+
+    size_t srcElementSize = srcTypedArray->elementSize();
+    size_t srcLength = srcTypedArray->arrayLength();
+    size_t srcByteOffset = srcTypedArray->byteOffset();
+
+    if (srcLength + targetOffset > targetLength) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_InvalidArrayLength);
+    }
+
+    // If one of srcType and targetType contains the substring "Big" and the other does not, throw a TypeError exception.
+    auto srcTypedArrayType = srcTypedArray->typedArrayType();
+    bool isSrcBigIntArray = srcTypedArrayType == TypedArrayType::BigInt64 || srcTypedArrayType == TypedArrayType::BigUint64;
+    if (isBigIntArray != isSrcBigIntArray) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->TypedArray.string(), true, strings->set.string(), "Cannot mix BigIntArray with other Array");
+    }
+
+    size_t srcByteIndex = srcByteOffset;
+    if (srcBuffer == targetBuffer) {
+        size_t srcByteLength = srcTypedArray->byteLength();
+        srcBuffer = ArrayBufferObject::cloneArrayBuffer(state, targetBuffer, srcByteOffset, srcByteLength, state.context()->globalObject()->arrayBuffer());
+        srcByteIndex = 0;
+    }
+
+    size_t targetByteIndex = targetOffset * targetElementSize + targetByteOffset;
+    size_t limit = targetByteIndex + targetElementSize * srcLength;
+
+    if (srcTypedArray->typedArrayType() == target->typedArrayType()) {
+        while (targetByteIndex < limit) {
+            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8", true, "Unordered").
+            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, TypedArrayType::Uint8);
+            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, "Uint8", value, true, "Unordered").
+            targetBuffer->setValueInBuffer(state, targetByteIndex, TypedArrayType::Uint8, value);
+            srcByteIndex++;
+            targetByteIndex++;
+        }
+    } else {
+        while (targetByteIndex < limit) {
+            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, "Unordered").
+            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, srcTypedArray->typedArrayType());
+            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, "Unordered").
+            targetBuffer->setValueInBuffer(state, targetByteIndex, target->typedArrayType(), value);
+            srcByteIndex += srcElementSize;
+            targetByteIndex += targetElementSize;
+        }
+    }
+
+    return Value();
+}
+
+static Value builtinTypedArraySome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, some);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.some as defined in 22.1.3.23 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
+                                       state.context()->staticStrings().some.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    Value T;
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let k be 0.
+    size_t k = 0;
+
+    // Repeat, while k < len
+    while (k < len) {
+        ObjectGetResult kResult = O->getIndexedProperty(state, Value(k));
+        // Let kValue be the result of calling the [[Get]] internal method of O with argument ToString(k).
+        Value kValue = kResult.value(state, O);
+        // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+        Value args[] = { kValue, Value(k), O };
+        Value testResult = Object::call(state, callbackfn, T, 3, args);
+
+        // If ToBoolean(testResult) is true, return true.
+        if (testResult.toBoolean(state)) {
+            return Value(true);
+        }
+
+        // Increase k by 1.
+        k++;
+    }
+    // Return false.
+    return Value(false);
+}
+
+static Value builtinTypedArraySort(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, sort);
+    // Let buffer be TypedArrayObject::validateTypedArray(obj).
+    ArrayBuffer* buffer = TypedArrayObject::validateTypedArray(state, O);
+
+    // Let len be the value of O’s [[ArrayLength]] internal slot.
+    int64_t len = O->asTypedArrayObject()->arrayLength();
+
+    Value cmpfn = argv[0];
+    if (!cmpfn.isUndefined() && !cmpfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
+    }
+    bool defaultSort = (argc == 0) || cmpfn.isUndefined();
+
+    // [defaultSort, &cmpfn, &state, &buffer]
+    O->sort(state, len, [&](const Value& x, const Value& y) -> bool {
+        ASSERT((x.isNumber() || x.isBigInt()) && (y.isNumber() || y.isBigInt()));
+        if (!defaultSort) {
+            Value args[] = { x, y };
+            double v = Object::call(state, cmpfn, Value(), 2, args).toNumber(state);
+            buffer->throwTypeErrorIfDetached(state);
+            if (std::isnan(v)) {
+                return false;
+            }
+            return (v < 0);
+        } else {
+            if (LIKELY(x.isNumber())) {
+                double xNum = x.asNumber();
+                double yNum = y.asNumber();
+
+                // 22.2.3.25.3-10
+                if (std::isnan(xNum)) {
+                    return false;
+                }
+
+                if (std::isnan(yNum)) {
+                    return true;
+                }
+
+                if (xNum == 0.0 && xNum == yNum) {
+                    return std::signbit(xNum);
+                }
+
+                return xNum <= yNum;
+            } else {
+                return x.asBigInt()->lessThanEqual(y.asBigInt());
+            }
+        } });
+    return O;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.subarray
+static Value builtinTypedArraySubArray(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the this value.
+    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(O, TypedArray, subarray);
+
+    // Let buffer be O.[[ViewedArrayBuffer]].
+    ArrayBuffer* buffer = O->buffer();
+    // Let srcLength be O.[[ArrayLength]].
+    double srcLength = O->arrayLength();
+    // Let relativeBegin be ToInteger(begin).
+    double relativeBegin = argv[0].toInteger(state);
+    // If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin), 0); else let beginIndex be min(relativeBegin, srcLength).
+    double beginIndex = (relativeBegin < 0) ? std::max((srcLength + relativeBegin), 0.0) : std::min(relativeBegin, srcLength);
+    // If end is undefined, let relativeEnd be srcLength; else, let relativeEnd be ToInteger(end).
+    double relativeEnd = srcLength;
+    if (!argv[1].isUndefined()) {
+        relativeEnd = argv[1].toInteger(state);
+    }
+    // If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd), 0); else let endIndex be min(relativeEnd, srcLength).
+    double endIndex = (relativeEnd < 0) ? std::max((srcLength + relativeEnd), 0.0) : std::min(relativeEnd, srcLength);
+
+    // Let newLength be max(endIndex – beginIndex, 0).
+    double newLength = std::max((int)(endIndex - beginIndex), 0);
+
+    // Let constructorName be the String value of O’s [[TypedArrayName]] internal slot.
+    // Let elementSize be the Number value of the Element Size value specified in Table 49 for constructorName.
+    size_t elementSize = O->elementSize();
+    // Let srcByteOffset be the value of O’s [[ByteOffset]] internal slot.
+    size_t srcByteOffset = O->byteOffset();
+    // Let beginByteOffset be srcByteOffset + beginIndex × elementSize.
+    size_t beginByteOffset = srcByteOffset + beginIndex * elementSize;
+
+    // Let argumentsList be «buffer, beginByteOffset, newLength».
+    Value args[3] = { buffer, Value(beginByteOffset), Value(newLength) };
+    // Return ? TypedArraySpeciesCreate(O, argumentsList).
+    return TypedArraySpeciesCreate(state, O, 3, args);
+}
+
+static Value builtinTypedArrayEvery(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, every);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.every as defined in 22.1.3.5 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    unsigned len = O->asTypedArrayObject()->arrayLength();
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
+                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1)
+        T = argv[1];
+
+    // Let k be 0.
+    size_t k = 0;
+
+    while (k < len) {
+        ObjectGetResult value = O->getIndexedProperty(state, Value(k));
+        // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+        Value kValue = value.value(state, O);
+        // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
+        Value args[] = { kValue, Value(k), O };
+        Value testResult = Object::call(state, callbackfn, T, 3, args);
+
+        if (!testResult.toBoolean(state)) {
+            return Value(false);
+        }
+
+        // Increae k by 1.
+        k++;
+    }
+    return Value(true);
+}
+
+//https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.fill
+static Value builtinTypedArrayFill(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
+
+    // Let len be O.[[ArrayLength]].
+    size_t len = O->arrayLength();
+
+    Value value(Value::ForceUninitialized);
+    // If O.[[TypedArrayName]] is "BigUint64Array" or "BigInt64Array", let value be ? ToBigInt(value).
+    auto typedArrayType = O->asTypedArrayObject()->typedArrayType();
+    if (UNLIKELY(typedArrayType == TypedArrayType::BigInt64 || typedArrayType == TypedArrayType::BigUint64)) {
+        value = argv[0].toBigInt(state);
+    } else {
+        // Otherwise, let value be ? ToNumber(value).
+        // Set value to ? ToNumber(value).
+        value = Value(argv[0].toNumber(state));
+    }
+    // Let relativeStart be ? ToInteger(start).
+    double relativeStart = 0;
+    if (argc > 1) {
+        relativeStart = argv[1].toInteger(state);
+    }
+    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
+    size_t k = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
+    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
+    double relativeEnd = len;
+    if (argc > 2 && !argv[2].isUndefined()) {
+        relativeEnd = argv[2].toInteger(state);
+    }
+    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
+    size_t fin = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
+
+    // If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
+    O->buffer()->throwTypeErrorIfDetached(state);
+
+    // Repeat, while k < final
+    while (k < fin) {
+        O->setIndexedPropertyThrowsException(state, Value(k), value);
+        k++;
+    }
+    // return O.
+    return O;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.filter
+static Value builtinTypedArrayFilter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
+
+    // Let len be O.[[ArrayLength]].
+    size_t len = O->arrayLength();
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().filter.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let kept be a new empty List.
+    ValueVectorWithInlineStorage kept;
+    // Let k be 0.
+    size_t k = 0;
+    // Let captured be 0.
+    size_t captured = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+        Value args[] = { kValue, Value(k), O };
+        bool selected = Object::call(state, callbackfn, T, 3, args).toBoolean(state);
+        if (selected) {
+            kept.push_back(kValue);
+            captured++;
+        }
+        k++;
+    }
+
+    // Let A be ? TypedArraySpeciesCreate(O, « captured »).
+    Value arg[1] = { Value(captured) };
+    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
+
+    // Let n be 0.
+    // For each element e of kept
+    for (size_t n = 0; n < kept.size(); n++) {
+        // Let status be Set(A, ToString(n), e, true ).
+        A.asObject()->setIndexedPropertyThrowsException(state, Value(n), kept[n]);
+    }
+    // Return A.
+    return A;
+}
+
+static Value builtinTypedArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, find);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.find as defined in 22.1.3.8 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    // If IsCallable(predicate) is false, throw a TypeError exception.
+    Value predicate = argv[0];
+    if (!predicate.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let k be 0.
+    size_t k = 0;
+    Value kValue;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let kValue be Get(O, Pk).
+        kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+        // Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
+        Value args[] = { kValue, Value(k), O };
+        bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
+        // If testResult is true, return kValue.
+        if (testResult) {
+            return kValue;
+        }
+        // Increase k by 1.
+        k++;
+    }
+    // Return undefined.
+    return Value();
+}
+
+static Value builtinTypedArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, findIndex);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.findIndex as defined in 22.1.3.9 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    // If IsCallable(predicate) is false, throw a TypeError exception.
+    Value predicate = argv[0];
+    if (!predicate.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let k be 0.
+    size_t k = 0;
+    Value kValue;
+    // Repeat, while k < len
+    while (k < len) {
+        // Let kValue be ? Get(O, Pk).
+        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+        Value args[] = { kValue, Value(k), O };
+        bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
+        // If testResult is true, return k.
+        if (testResult) {
+            return Value(k);
+        }
+        // Increase k by 1.
+        k++;
+    }
+    // Return -1
+    return Value(-1);
+}
+
+static Value builtinTypedArrayForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, forEach);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.forEach as defined in 22.1.3.10 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
+                                       state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let k be 0.
+    size_t k = 0;
+    while (k < len) {
+        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
+        Value kValue = res.value(state, O);
+        Value args[] = { kValue, Value(k), O };
+        Object::call(state, callbackfn, T, 3, args);
+        k++;
+    }
+    // Return undefined.
+    return Value();
+}
+
+static Value builtinTypedArrayJoin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, join);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.join as defined in 22.1.3.12 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    Value separator = argv[0];
+    size_t lenMax = STRING_MAXIMUM_LENGTH;
+    String* sep;
+
+    if (separator.isUndefined()) {
+        sep = state.context()->staticStrings().asciiTable[(size_t)','].string();
+    } else {
+        sep = separator.toString(state);
+    }
+
+    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(O) || len == 0) {
+        return String::emptyString;
+    }
+    ToStringRecursionPreventerItemAutoHolder holder(state, O);
+
+    StringBuilder builder;
+    Value elem = O->getIndexedProperty(state, Value(0)).value(state, O);
+    if (elem.isUndefinedOrNull()) {
+        elem = String::emptyString;
+    }
+    builder.appendString(elem.toString(state));
+
+    size_t curIndex = 1;
+    while (curIndex < len) {
+        if (sep->length() > 0) {
+            if (static_cast<double>(builder.contentLength()) > static_cast<double>(lenMax - sep->length())) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
+            }
+            builder.appendString(sep);
+        }
+        elem = O->getIndexedProperty(state, Value(curIndex)).value(state, O);
+        if (elem.isUndefinedOrNull()) {
+            elem = String::emptyString;
+        }
+        builder.appendString(elem.toString(state));
+        curIndex++;
+    }
+
+    return builder.finalize(&state);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.map
+static Value builtinTypedArrayMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
+
+    // Let len be O.[[ArrayLength]].
+    size_t len = O->arrayLength();
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().map.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If thisArg was supplied, let T be thisArg; else let T be undefined.
+    Value T;
+    if (argc > 1) {
+        T = argv[1];
+    }
+
+    // Let A be ? TypedArraySpeciesCreate(O, « len »).
+    Value arg[1] = { Value(len) };
+    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
+
+    // Let k be 0.
+    size_t k = 0;
+    // Repeat, while k < len
+    while (k < len) {
+        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+        Value args[] = { kValue, Value(k), O };
+        Value mappedValue = Object::call(state, callbackfn, T, 3, args);
+        A.asObject()->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
+        k++;
+    }
+    // Return A.
+    return A;
+}
+
+static Value builtinTypedArrayReduce(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reduce);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.reduce as defined in 22.1.3.18 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    if (len == 0 && argc < 2) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+    }
+
+    size_t k = 0; // 6
+    Value accumulator;
+    if (argc > 1) { // 7
+        accumulator = argv[1];
+    } else { // 8
+        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
+        accumulator = res.value(state, O);
+        k++;
+    }
+    while (k < len) { // 9
+        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
+        Value kValue = res.value(state, O);
+        Value args[] = { accumulator, kValue, Value(k), O };
+        accumulator = Object::call(state, callbackfn, Value(), 4, args);
+        k++;
+    }
+    return accumulator;
+}
+
+static Value builtinTypedArrayReduceRight(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reduceRight);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.reduceRight as defined in 22.1.3.19 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    double len = O->asTypedArrayObject()->arrayLength();
+
+    // If IsCallable(callbackfn) is false, throw a TypeError exception.
+    Value callbackfn = argv[0];
+    if (!callbackfn.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
+                                       state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+    }
+
+    // If len is 0 and initialValue is not present, throw a TypeError exception.
+    if (len == 0 && argc < 2) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
+    }
+
+    // Let k be len-1.
+    int64_t k = len - 1;
+
+    Value accumulator;
+    // If initialValue is present, then
+    if (argc > 1) {
+        // Set accumulator to initialValue.
+        accumulator = argv[1];
+    } else {
+        // Else, initialValue is not present
+        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
+        accumulator = res.value(state, O);
+        k--;
+    }
+
+    // Repeat, while k ≥ 0
+    while (k >= 0) {
+        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
+        Value kValue = res.value(state, O);
+        Value args[] = { accumulator, kValue, Value(k), O };
+        accumulator = Object::call(state, callbackfn, Value(), 4, args);
+        k--;
+    }
+    // Return accumulator.
+    return accumulator;
+}
+
+static Value builtinTypedArrayReverse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reverse);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, O);
+
+    // Array.prototype.reverse as defined in 22.1.3.20 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    size_t len = O->asTypedArrayObject()->arrayLength();
+    size_t middle = std::floor(len / 2);
+    size_t lower = 0;
+    while (middle > lower) {
+        size_t upper = len - lower - 1;
+
+        ObjectGetResult upperResult = O->getIndexedProperty(state, Value(upper));
+        ObjectGetResult lowerResult = O->getIndexedProperty(state, Value(lower));
+        RELEASE_ASSERT(upperResult.hasValue() && lowerResult.hasValue());
+
+        Value upperValue = upperResult.value(state, O);
+        Value lowerValue = lowerResult.value(state, O);
+
+        if (!O->setIndexedProperty(state, Value(lower), upperValue)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::DefineProperty_NotWritable);
+        }
+        if (!O->setIndexedProperty(state, Value(upper), lowerValue)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::DefineProperty_NotWritable);
+        }
+
+        lower++;
+    }
+    return O;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.slice
+static Value builtinTypedArraySlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be the this value.
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
+
+    // Let len be the value of O’s [[ArrayLength]] internal slot.
+    size_t len = O->arrayLength();
+    // Let relativeStart be ToInteger(start).
+    double relativeStart = argv[0].toInteger(state);
+    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
+    size_t k = (relativeStart < 0) ? std::max((double)len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
+    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
+    double relativeEnd = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
+    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
+    double finalEnd = (relativeEnd < 0) ? std::max((double)len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
+    // Let count be max(final – k, 0).
+    size_t count = std::max((double)finalEnd - k, 0.0);
+
+    Value arg[1] = { Value(count) };
+    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
+    TypedArrayObject* target = A.asObject()->asTypedArrayObject();
+
+    // If SameValue(srcType, targetType) is false, then
+    if (O->typedArrayType() != target->typedArrayType()) {
+        size_t n = 0;
+        while (k < finalEnd) {
+            O->buffer()->throwTypeErrorIfDetached(state);
+            Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+            A.asObject()->setIndexedPropertyThrowsException(state, Value(n), kValue);
+            k++;
+            n++;
+        }
+    } else if (count > 0) {
+        // Else if count > 0,
+        ArrayBuffer* srcBuffer = O->buffer();
+        srcBuffer->throwTypeErrorIfDetached(state);
+        ArrayBuffer* targetBuffer = target->buffer();
+
+        size_t elementSize = O->elementSize();
+        size_t srcByteOffset = O->byteOffset();
+        size_t targetByteIndex = target->byteOffset();
+        size_t srcByteIndex = (size_t)k * elementSize + srcByteOffset;
+        size_t limit = targetByteIndex + count * elementSize;
+
+        while (targetByteIndex < limit) {
+            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8", true, "Unordered").
+            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, TypedArrayType::Uint8);
+            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, "Uint8", value, true, "Unordered").
+            targetBuffer->setValueInBuffer(state, targetByteIndex, TypedArrayType::Uint8, value);
+            srcByteIndex++;
+            targetByteIndex++;
+        }
+    }
+
+    return A;
+}
+
+static Value builtinTypedArrayToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Let O be ToObject(this value).
+    RESOLVE_THIS_BINDING_TO_OBJECT(array, TypedArray, toLocaleString);
+    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+    TypedArrayObject::validateTypedArray(state, array);
+
+    // Array.prototype.toLocaleString as defined in 22.1.3.26 except
+    // that the this object’s [[ArrayLength]] internal slot is accessed
+    // in place of performing a [[Get]] of "length"
+    size_t len = array->asTypedArrayObject()->arrayLength();
+
+    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(array)) {
+        return String::emptyString;
+    }
+    ToStringRecursionPreventerItemAutoHolder holder(state, array);
+
+    // Let separator be the String value for the list-separator String appropriate for the host environment’s current locale (this is derived in an implementation-defined way).
+    String* separator = state.context()->staticStrings().asciiTable[(size_t)','].string();
+
+    // Let R be the empty String.
+    String* R = String::emptyString;
+
+    // Let k be 0.
+    size_t k = 0;
+
+    // Repeat, while k < len
+    while (k < len) {
+        // If k > 0, then
+        if (k > 0) {
+            // Set R to the string-concatenation of R and separator.
+            StringBuilder builder;
+            builder.appendString(R);
+            builder.appendString(separator);
+            R = builder.finalize(&state);
+        }
+        // Let nextElement be ? Get(array, ! ToString(k)).
+        Value nextElement = array->getIndexedProperty(state, Value(k)).value(state, array);
+        // If nextElement is not undefined or null, then
+        ASSERT(!nextElement.isUndefinedOrNull());
+        // Let S be ? ToString(? Invoke(nextElement, "toLocaleString")).
+        Value func = nextElement.toObject(state)->get(state, state.context()->staticStrings().toLocaleString).value(state, nextElement);
+        String* S = Object::call(state, func, nextElement, 0, nullptr).toString(state);
+        // Set R to the string-concatenation of R and S.
+        StringBuilder builder2;
+        builder2.appendString(R);
+        builder2.appendString(S);
+        R = builder2.finalize(&state);
+        // Increase k by 1.
+        k++;
+    }
+
+    // Return R.
+    return R;
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.keys
+static Value builtinTypedArrayKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    // Return CreateArrayIterator(O, "key").
+    return thisValue.asObject()->keys(state);
+}
+
+static Value builtinTypedArrayValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // Perform ? TypedArrayObject::validateTypedArray(O).
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    return thisValue.asObject()->values(state);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.entries
+static Value builtinTypedArrayEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    return thisValue.asObject()->entries(state);
+}
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype-@@tostringtag
+static Value builtinTypedArrayToStringTagGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    Value O = thisValue;
+    if (!O.isObject()) {
+        return Value();
+    }
+
+    if (O.asObject()->isTypedArrayObject()) {
+        return Value(O.asObject()->asTypedArrayObject()->typedArrayName(state));
+    }
+    return Value();
+}
+
+static Value builtinTypedArrayAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    TypedArrayObject::validateTypedArray(state, thisValue);
+    Object* obj = thisValue.asObject();
+    size_t len = obj->length(state);
+    double relativeStart = argv[0].toInteger(state);
+    if (relativeStart < 0) {
+        relativeStart = len + relativeStart;
+    }
+    if (relativeStart < 0 || relativeStart >= len) {
+        return Value();
+    }
+    return obj->getIndexedProperty(state, Value(relativeStart)).value(state, thisValue);
+}
+
+template <typename TA, int elementSize>
+FunctionObject* GlobalObject::installTypedArray(ExecutionState& state, AtomicString taName, Object** proto, FunctionObject* typedArrayFunction)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+    NativeFunctionObject* taConstructor = new NativeFunctionObject(state, NativeFunctionInfo(taName, builtinTypedArrayConstructor<TA>, 3), NativeFunctionObject::__ForBuiltinConstructor__);
+    taConstructor->setGlobalIntrinsicObject(state);
+
+    *proto = m_objectPrototype;
+    Object* taPrototype = new TypedArrayPrototypeObject(state);
+    taPrototype->setGlobalIntrinsicObject(state, true);
+    taPrototype->setPrototype(state, typedArrayFunction->getFunctionPrototype(state));
+
+    taConstructor->setPrototype(state, typedArrayFunction); // %TypedArray%
+    taConstructor->setFunctionPrototype(state, taPrototype);
+
+    // 22.2.5.1 /TypedArray/.BYTES_PER_ELEMENT
+    taConstructor->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->BYTES_PER_ELEMENT), ObjectPropertyDescriptor(Value(elementSize), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ValuePresent)));
+
+    // 22.2.6.1 /TypedArray/.prototype.BYTES_PER_ELEMENT
+    taPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->BYTES_PER_ELEMENT), ObjectPropertyDescriptor(Value(elementSize), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ValuePresent)));
+
+    // 22.2.6.2 /TypedArray/.prototype.constructor
+    taPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    defineOwnProperty(state, ObjectPropertyName(taName),
+                      ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    return taConstructor;
+}
+
+void GlobalObject::installTypedArray(ExecutionState& state)
+{
+    const StaticStrings* strings = &state.context()->staticStrings();
+
+    // %TypedArray%
+    FunctionObject* typedArrayFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->TypedArray, builtinTypedArrayConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    typedArrayFunction->setGlobalIntrinsicObject(state);
+
+    typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->from),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->from, builtinTypedArrayFrom, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->of),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->of, builtinTypedArrayOf, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
+    }
+
+
+    // %TypedArray%.prototype
+    Object* typedArrayPrototype = typedArrayFunction->getFunctionPrototype(state).asObject();
+    typedArrayPrototype->setGlobalIntrinsicObject(state, true);
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->subarray),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->subarray, builtinTypedArraySubArray, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->set),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->set, builtinTypedArraySet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->some),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->some, builtinTypedArraySome, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->sort),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->sort, builtinTypedArraySort, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->copyWithin),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->copyWithin, builtinTypedArrayCopyWithin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->every),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->every, builtinTypedArrayEvery, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fill),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fill, builtinTypedArrayFill, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->filter),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->filter, builtinTypedArrayFilter, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->find),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->find, builtinTypedArrayFind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->findIndex),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->findIndex, builtinTypedArrayFindIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->forEach),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->forEach, builtinTypedArrayForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->join),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->join, builtinTypedArrayJoin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->map),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->map, builtinTypedArrayMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reduce),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reduce, builtinTypedArrayReduce, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reduceRight),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reduceRight, builtinTypedArrayReduceRight, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reverse),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reverse, builtinTypedArrayReverse, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinTypedArraySlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleString),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleString, builtinTypedArrayToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.tostring
+    // The initial value of the %TypedArray%.prototype.toString data property is the same built-in function object as the Array.prototype.toString method
+    ASSERT(!!m_arrayPrototype && m_arrayPrototype->hasOwnProperty(state, ObjectPropertyName(strings->toString)));
+    Value arrayToString = m_arrayPrototype->getOwnProperty(state, ObjectPropertyName(strings->toString)).value(state, m_arrayPrototype);
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
+                                                          ObjectPropertyDescriptor(arrayToString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->indexOf),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->indexOf, builtinTypedArrayIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->lastIndexOf),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lastIndexOf, builtinTypedArrayLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->includes),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->includes, builtinTypedArrayIncludes, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->keys),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->keys, builtinTypedArrayKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->entries),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->entries, builtinTypedArrayEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->at),
+                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->at, builtinTypedArrayAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+
+    auto valuesFn = new NativeFunctionObject(state, NativeFunctionInfo(strings->values, builtinTypedArrayValues, 0, NativeFunctionInfo::Strict));
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->values),
+                                                          ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+                                                          ObjectPropertyDescriptor(valuesFn,
+                                                                                   (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolToStringTag, builtinTypedArrayToStringTagGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag), desc);
+    }
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinTypedArrayByteLengthGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor byteLengthDesc2(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc2);
+    }
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteOffset, builtinTypedArrayByteOffsetGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor byteOffsetDesc2(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteOffset), byteOffsetDesc2);
+    }
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getLength, builtinTypedArrayLengthGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor lengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->length), lengthDesc);
+    }
+    {
+        JSGetterSetter gs(
+            new NativeFunctionObject(state, NativeFunctionInfo(strings->getBuffer, builtinTypedArrayBufferGetter, 0, NativeFunctionInfo::Strict)),
+            Value(Value::EmptyValue));
+        ObjectPropertyDescriptor bufferDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->buffer), bufferDesc);
+    }
+
+    m_typedArray = typedArrayFunction;
+    m_typedArrayPrototype = typedArrayFunction->getFunctionPrototype(state).asObject();
+#define INSTALL_TYPEDARRAY(TYPE, type, siz, nativeType)                                                                                      \
+    m_##type##Array = installTypedArray<TYPE##ArrayObject, siz>(state, strings->TYPE##Array, &m_##type##ArrayPrototype, typedArrayFunction); \
+    m_##type##ArrayPrototype = m_##type##Array->getFunctionPrototype(state).asObject();
+
+    FOR_EACH_TYPEDARRAY_TYPES(INSTALL_TYPEDARRAY)
+#undef INSTALL_TYPEDARRAY
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakMap.cpp
new file mode 100644 (file)
index 0000000..e272011
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/WeakMapObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+static Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    // Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
+    // Set map's [[MapData]] internal slot to a new empty List.
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->weakMapPrototype();
+    });
+    WeakMapObject* map = new WeakMapObject(state, proto);
+
+    // If iterable is not present, or is either undefined or null, return map.
+    if (argc == 0 || argv[0].isUndefinedOrNull()) {
+        return map;
+    }
+
+    Value iterable = argv[0];
+
+    // Let adder be ? Get(map, "set").
+    Value adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map);
+    // If IsCallable(adder) is false, throw a TypeError exception.
+    if (!adder.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
+    }
+
+    // Let iteratorRecord be ? GetIterator(iterable).
+    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
+    while (true) {
+        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
+        if (!next.hasValue()) {
+            return map;
+        }
+
+        Value nextItem = IteratorObject::iteratorValue(state, next.value());
+        if (!nextItem.isObject()) {
+            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
+            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
+        }
+
+        try {
+            // Let k be Get(nextItem, "0").
+            // If k is an abrupt completion, return ? IteratorClose(iter, k).
+            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
+            // Let v be Get(nextItem, "1").
+            // If v is an abrupt completion, return ? IteratorClose(iter, v).
+            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
+
+            // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »).
+            Value argv[2] = { k, v };
+            Object::call(state, adder, map, 2, argv);
+        } catch (const Value& v) {
+            // we should save thrown value bdwgc cannot track thrown value
+            Value exceptionValue = v;
+            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
+            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+        }
+    }
+
+    return map;
+}
+
+#define RESOLVE_THIS_BINDING_TO_WEAKMAP(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                      \
+    if (!thisValue.isObject() || !thisValue.asObject()->isWeakMapObject()) {                                                                                                                                                                             \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                    \
+    WeakMapObject* NAME = thisValue.asObject()->asWeakMapObject();
+
+static Value builtinWeakMapDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, stringDelete);
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+
+    return Value(M->deleteOperation(state, argv[0].asObject()));
+}
+
+static Value builtinWeakMapGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, get);
+    if (!argv[0].isObject()) {
+        return Value();
+    }
+
+    return M->get(state, argv[0].asObject());
+}
+
+static Value builtinWeakMapHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, has);
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+
+    return Value(M->has(state, argv[0].asObject()));
+}
+
+static Value builtinWeakMapSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, set);
+    if (!argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Invalid value used as weak map key");
+    }
+
+    M->set(state, argv[0].asObject(), argv[1]);
+    return M;
+}
+
+void GlobalObject::installWeakMap(ExecutionState& state)
+{
+    m_weakMap = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakMap, builtinWeakMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_weakMap->setGlobalIntrinsicObject(state);
+
+    m_weakMapPrototype = new Object(state, m_objectPrototype);
+    m_weakMapPrototype->setGlobalIntrinsicObject(state, true);
+    m_weakMapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinWeakMapDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinWeakMapGet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinWeakMapHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinWeakMapSet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakMap.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakMap->setFunctionPrototype(state, m_weakMapPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap),
+                      ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakRef.cpp
new file mode 100644 (file)
index 0000000..b5c122e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/WeakRefObject.h"
+#include "runtime/NativeFunctionObject.h"
+
+namespace Escargot {
+
+static Value builtinWeakRefConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+    if (argc == 0 || !argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target is not object");
+    }
+
+    // Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRefPrototype%", « [[WeakRefTarget]] »).
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->weakRefPrototype();
+    });
+    WeakRefObject* weakRef = new WeakRefObject(state, proto, argv[0].asObject());
+
+    return weakRef;
+}
+
+
+static Value builtinWeakRefDeRef(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    if (!thisValue.isObject() || !thisValue.asObject()->isWeakRefObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
+    }
+    // Let weakRef be the this value.
+    WeakRefObject* weakRef = thisValue.asObject()->asWeakRefObject();
+    return weakRef->targetAsValue();
+}
+
+
+void GlobalObject::installWeakRef(ExecutionState& state)
+{
+    m_weakRef = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakRef, builtinWeakRefConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_weakRef->setGlobalIntrinsicObject(state);
+
+    m_weakRefPrototype = new Object(state, m_objectPrototype);
+    m_weakRefPrototype->setGlobalIntrinsicObject(state, true);
+    m_weakRefPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakRefPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().deref),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().deref, builtinWeakRefDeRef, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    // WeakRef.prototype.deref
+    m_weakRefPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakRef.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakRef->setFunctionPrototype(state, m_weakRefPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakRef),
+                      ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/builtins/BuiltinWeakSet.cpp
new file mode 100644 (file)
index 0000000..a73d967
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2018-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+#include "runtime/Context.h"
+#include "runtime/VMInstance.h"
+#include "runtime/WeakSetObject.h"
+#include "runtime/IteratorObject.h"
+#include "runtime/NativeFunctionObject.h"
+#include "runtime/ToStringRecursionPreventer.h"
+
+namespace Escargot {
+
+// https://www.ecma-international.org/ecma-262/10.0/#sec-weakset-constructor
+static Value builtinWeakSetConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    // If NewTarget is undefined, throw a TypeError exception.
+    if (!newTarget.hasValue()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
+    }
+
+    // Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSetPrototype%", « [[WeakSetData]] »).
+    // Set set's [[WeakSetData]] internal slot to a new empty List.
+    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
+        return constructorRealm->globalObject()->weakSetPrototype();
+    });
+    WeakSetObject* set = new WeakSetObject(state, proto);
+
+    // If iterable is not present, let iterable be undefined.
+    Value iterable;
+    if (argc > 0) {
+        iterable = argv[0];
+    }
+
+    // If iterable is either undefined or null, return set.
+    if (iterable.isUndefinedOrNull()) {
+        return set;
+    }
+
+    // Let adder be ? Get(set, "add").
+    Value adder = set->get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set);
+    // If IsCallable(adder) is false, throw a TypeError exception.
+    if (!adder.isCallable()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
+    }
+
+    // Let iteratorRecord be ? GetIterator(iterable).
+    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
+
+    // Repeat
+    while (true) {
+        // Let next be ? IteratorStep(iteratorRecord).
+        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
+        // If next is false, return set.
+        if (!next.hasValue()) {
+            return set;
+        }
+        // Let nextValue be ? IteratorValue(next).
+        Value nextValue = IteratorObject::iteratorValue(state, next.value());
+
+        // Let status be Call(adder, set, « nextValue »).
+        try {
+            Value argv[1] = { nextValue };
+            Object::call(state, adder, set, 1, argv);
+        } catch (const Value& v) {
+            // we should save thrown value bdwgc cannot track thrown value
+            Value exceptionValue = v;
+            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
+            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
+        }
+    }
+    return set;
+}
+
+#define RESOLVE_THIS_BINDING_TO_WEAKSET(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                      \
+    if (!thisValue.isObject() || !thisValue.asObject()->isWeakSetObject()) {                                                                                                                                                                             \
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
+    }                                                                                                                                                                                                                                                    \
+    WeakSetObject* NAME = thisValue.asObject()->asWeakSetObject();
+
+static Value builtinWeakSetAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, add);
+    if (!argv[0].isObject()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Invalid value used as weak set key");
+    }
+
+    S->add(state, argv[0].asObject());
+    return S;
+}
+
+static Value builtinWeakSetDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, stringDelete);
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+
+    return Value(S->deleteOperation(state, argv[0].asObject()));
+}
+
+static Value builtinWeakSetHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, has);
+    if (!argv[0].isObject()) {
+        return Value(false);
+    }
+
+    return Value(S->has(state, argv[0].asObject()));
+}
+
+void GlobalObject::installWeakSet(ExecutionState& state)
+{
+    m_weakSet = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakSet, builtinWeakSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
+    m_weakSet->setGlobalIntrinsicObject(state);
+
+    m_weakSetPrototype = new Object(state);
+    m_weakSetPrototype->setGlobalIntrinsicObject(state, true);
+
+    m_weakSetPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinWeakSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinWeakSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
+                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinWeakSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
+                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakSet.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+
+    m_weakSet->setFunctionPrototype(state, m_weakSetPrototype);
+    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakSet),
+                      ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
index 31e4b6a6408ab42fcba4a0bbd22e4648a584fc5d..1c284c6d09557f8a29f832ddaec00cf8a669408c 100644 (file)
@@ -27,7 +27,7 @@
 #include "parser/CodeBlock.h"
 #include "interpreter/ByteCode.h"
 #include "runtime/Context.h"
-#include "runtime/VMInstance.h"
+#include "runtime/ThreadLocal.h"
 #include "runtime/ObjectStructurePropertyName.h"
 
 namespace Escargot {
@@ -867,7 +867,7 @@ ByteCodeBlock* CodeCacheReader::loadByteCodeBlock(Context* context, InterpretedC
     size = m_buffer.get<size_t>();
     bigIntData.resizeWithUninitializedValues(size);
     for (size_t i = 0; i < size; i++) {
-        bigIntData[i] = new BigInt(m_buffer.getBF(VMInstance::bfContext()));
+        bigIntData[i] = new BigInt(m_buffer.getBF(ThreadLocal::bfContext()));
     }
 
     // ByteCodeBlock::m_code bytecode stream
index fbb0c187c20bafcba738194e477a4e3dfa7ad93b..22952e705460441d80b57fa8a6f0454046896016 100644 (file)
@@ -20,6 +20,8 @@
 #include "Escargot.h"
 #include "ByteCode.h"
 #include "ByteCodeInterpreter.h"
+#include "runtime/Global.h"
+#include "runtime/Platform.h"
 #include "runtime/Environment.h"
 #include "runtime/EnvironmentRecord.h"
 #include "runtime/FunctionObject.h"
@@ -3420,8 +3422,8 @@ NEVER_INLINE void ByteCodeInterpreter::callFunctionComplexCase(ExecutionState& s
         // Perform ! PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
         innerPromiseCapability.m_promise->asPromiseObject()->then(state, onFulfilled, onRejected);
 
-        state.context()->vmInstance()->platform()->hostImportModuleDynamically(byteCodeBlock->m_codeBlock->context(),
-                                                                               referencingScriptOrModule, specifierString, innerPromiseCapability.m_promise->asPromiseObject());
+        Global::platform()->hostImportModuleDynamically(byteCodeBlock->m_codeBlock->context(),
+                                                        referencingScriptOrModule, specifierString, innerPromiseCapability.m_promise->asPromiseObject());
 
         // Return promiseCapability.[[Promise]].
         registerFile[code->m_resultIndex] = promiseCapability.m_promise;
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.cpp
new file mode 100644 (file)
index 0000000..c7e236a
--- /dev/null
@@ -0,0 +1,2030 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
+ * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "runtime/Object.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/VMInstance.h"
+#include "Intl.h"
+#include "IntlLocale.h"
+
+namespace Escargot {
+
+// Invalid tags starting with: https://github.com/tc39/ecma402/pull/289
+static bool isValidTagInBCP47ButInvalidOnUTS35(const std::string& s)
+{
+    if (s.rfind("no-nyn", 0) == 0) {
+        return true;
+    } else if (s.rfind("i-klingon", 0) == 0) {
+        return true;
+    } else if (s.rfind("zh-hak-CN", 0) == 0) {
+        return true;
+    } else if (s.rfind("sgn-ils", 0) == 0) {
+        return true;
+    }
+
+    return false;
+}
+
+static std::string grandfatheredLangTag(const std::string& locale)
+{
+    // grandfathered = irregular / regular
+    std::unordered_map<std::string, std::string> tagMap;
+    // Irregular.
+    tagMap["en-gb-oed"] = "en-GB-oed";
+    tagMap["i-ami"] = "ami";
+    tagMap["i-bnn"] = "bnn";
+    tagMap["i-default"] = "i-default";
+    tagMap["i-enochian"] = "i-enochian";
+    tagMap["i-hak"] = "hak";
+    tagMap["i-klingon"] = "tlh";
+    tagMap["i-lux"] = "lb";
+    tagMap["i-mingo"] = "i-mingo";
+    tagMap["i-navajo"] = "nv";
+    tagMap["i-pwn"] = "pwn";
+    tagMap["i-tao"] = "tao";
+    tagMap["i-tay"] = "tay";
+    tagMap["i-tsu"] = "tsu";
+    tagMap["sgn-be-fr"] = "sfb";
+    tagMap["sgn-be-nl"] = "vgt";
+    tagMap["sgn-ch-de"] = "sgg";
+    // Regular.
+    tagMap["art-lojban"] = "jbo";
+    tagMap["cel-gaulish"] = "xtg-x-cel-gaulish";
+    tagMap["no-bok"] = "nb";
+    tagMap["no-nyn"] = "nn";
+    tagMap["zh-guoyu"] = "zh";
+    tagMap["zh-hakka"] = "hak";
+    tagMap["zh-min"] = "zh-min";
+    tagMap["zh-min-nan"] = "nan";
+    tagMap["zh-xiang"] = "hsn";
+
+    auto tempLocale = locale;
+    std::transform(tempLocale.begin(), tempLocale.end(), tempLocale.begin(), tolower);
+    auto iter = tagMap.find(tempLocale);
+
+    if (iter != tagMap.end()) {
+        return iter->second;
+    }
+    return std::string();
+}
+
+static std::string intlPreferredLanguageTag(const std::string& tag)
+{
+    // 78 possible replacements
+    if (tag == "aar")
+        return "aa";
+    if (tag == "aam")
+        return "aas";
+    if (tag == "adp")
+        return "dz";
+    if (tag == "aue")
+        return "ktz";
+    if (tag == "ayx")
+        return "nun";
+    if (tag == "bgm")
+        return "bcg";
+    if (tag == "bjd")
+        return "drl";
+    if (tag == "ccq")
+        return "rki";
+    if (tag == "ces")
+        return "cs";
+    if (tag == "cjr")
+        return "mom";
+    if (tag == "cka")
+        return "cmr";
+    if (tag == "cmk")
+        return "xch";
+    if (tag == "cmn")
+        return "zh";
+    if (tag == "coy")
+        return "pij";
+    if (tag == "cqu")
+        return "quh";
+    if (tag == "drh")
+        return "khk";
+    if (tag == "drw")
+        return "prs";
+    if (tag == "gav")
+        return "dev";
+    if (tag == "gfx")
+        return "vaj";
+    if (tag == "ggn")
+        return "gvr";
+    if (tag == "gti")
+        return "nyc";
+    if (tag == "guv")
+        return "duz";
+    if (tag == "heb")
+        return "he";
+    if (tag == "hrr")
+        return "jal";
+    if (tag == "ibi")
+        return "opa";
+    if (tag == "ilw")
+        return "gal";
+    if (tag == "in")
+        return "id";
+    if (tag == "iw")
+        return "he";
+    if (tag == "jeg")
+        return "oyb";
+    if (tag == "ji")
+        return "yi";
+    if (tag == "jw")
+        return "jv";
+    if (tag == "kgc")
+        return "tdf";
+    if (tag == "kgh")
+        return "kml";
+    if (tag == "koj")
+        return "kwv";
+    if (tag == "krm")
+        return "bmf";
+    if (tag == "ktr")
+        return "dtp";
+    if (tag == "kvs")
+        return "gdj";
+    if (tag == "kwq")
+        return "yam";
+    if (tag == "kxe")
+        return "tvd";
+    if (tag == "kzj")
+        return "dtp";
+    if (tag == "kzt")
+        return "dtp";
+    if (tag == "lii")
+        return "raq";
+    if (tag == "lmm")
+        return "rmx";
+    if (tag == "meg")
+        return "cir";
+    if (tag == "mo")
+        return "ro";
+    if (tag == "mst")
+        return "mry";
+    if (tag == "mwj")
+        return "vaj";
+    if (tag == "myt")
+        return "mry";
+    if (tag == "nad")
+        return "xny";
+    if (tag == "ncp")
+        return "kdz";
+    if (tag == "nnx")
+        return "ngv";
+    if (tag == "nts")
+        return "pij";
+    if (tag == "oun")
+        return "vaj";
+    if (tag == "pcr")
+        return "adx";
+    if (tag == "pmc")
+        return "huw";
+    if (tag == "pmu")
+        return "phr";
+    if (tag == "ppa")
+        return "bfy";
+    if (tag == "ppr")
+        return "lcq";
+    if (tag == "pry")
+        return "prt";
+    if (tag == "puz")
+        return "pub";
+    if (tag == "sca")
+        return "hle";
+    if (tag == "skk")
+        return "oyb";
+    if (tag == "tdu")
+        return "dtp";
+    if (tag == "thc")
+        return "tpo";
+    if (tag == "thx")
+        return "oyb";
+    if (tag == "tie")
+        return "ras";
+    if (tag == "tkk")
+        return "twm";
+    if (tag == "tlw")
+        return "weo";
+    if (tag == "tmp")
+        return "tyj";
+    if (tag == "tne")
+        return "kak";
+    if (tag == "tnf")
+        return "prs";
+    if (tag == "tsf")
+        return "taj";
+    if (tag == "uok")
+        return "ema";
+    if (tag == "xba")
+        return "cax";
+    if (tag == "xia")
+        return "acn";
+    if (tag == "xkh")
+        return "waw";
+    if (tag == "xsj")
+        return "suj";
+    if (tag == "ybd")
+        return "rki";
+    if (tag == "yma")
+        return "lrr";
+    if (tag == "ymt")
+        return "mtm";
+    if (tag == "yos")
+        return "zom";
+    if (tag == "yuu")
+        return "yug";
+    return "";
+}
+
+static std::string intlRedundantLanguageTag(const std::string& tag)
+{
+    // 24 possible replacements
+    if (tag == "hy-arevela")
+        return "hy";
+    if (tag == "hy-arevmda")
+        return "hyw";
+    if (tag == "ja-Latn-hepburn-heploc")
+        return "ja-Latn-alalc97";
+    if (tag == "sgn-BR")
+        return "bzs";
+    if (tag == "sgn-CO")
+        return "csn";
+    if (tag == "sgn-DE")
+        return "gsg";
+    if (tag == "sgn-DK")
+        return "dsl";
+    if (tag == "sgn-ES")
+        return "ssp";
+    if (tag == "sgn-FR")
+        return "fsl";
+    if (tag == "sgn-GB")
+        return "bfi";
+    if (tag == "gss")
+        return "sgn-GR";
+    if (tag == "sgn-IE")
+        return "isg";
+    if (tag == "sgn-IT")
+        return "ise";
+    if (tag == "sgn-JP")
+        return "jsl";
+    if (tag == "sgn-MX")
+        return "mfs";
+    if (tag == "sgn-NI")
+        return "ncs";
+    if (tag == "sgn-NL")
+        return "dse";
+    if (tag == "sgn-NO")
+        return "nsl";
+    if (tag == "sgn-PT")
+        return "psr";
+    if (tag == "sgn-SE")
+        return "swl";
+    if (tag == "sgn-US")
+        return "ase";
+    if (tag == "sgn-ZA")
+        return "sfs";
+    if (tag == "zh-cmn-Hans")
+        return "cmn-Hans";
+    if (tag == "zh-cmn-Hant")
+        return "cmn-Hant";
+    return "";
+}
+
+std::string Intl::preferredLanguage(const std::string& language)
+{
+    auto preferred = intlPreferredLanguageTag(language);
+    if (preferred != "") {
+        return preferred;
+    }
+    return language;
+}
+
+static std::string intlPreferredExtlangTag(const std::string& tag)
+{
+    // 235 possible replacements
+    if (tag == "aao")
+        return "ar";
+    if (tag == "abh")
+        return "ar";
+    if (tag == "abv")
+        return "ar";
+    if (tag == "acm")
+        return "ar";
+    if (tag == "acq")
+        return "ar";
+    if (tag == "acw")
+        return "ar";
+    if (tag == "acx")
+        return "ar";
+    if (tag == "acy")
+        return "ar";
+    if (tag == "adf")
+        return "ar";
+    if (tag == "ads")
+        return "sgn";
+    if (tag == "aeb")
+        return "ar";
+    if (tag == "aec")
+        return "ar";
+    if (tag == "aed")
+        return "sgn";
+    if (tag == "aen")
+        return "sgn";
+    if (tag == "afb")
+        return "ar";
+    if (tag == "afg")
+        return "sgn";
+    if (tag == "ajp")
+        return "ar";
+    if (tag == "apc")
+        return "ar";
+    if (tag == "apd")
+        return "ar";
+    if (tag == "arb")
+        return "ar";
+    if (tag == "arq")
+        return "ar";
+    if (tag == "ars")
+        return "ar";
+    if (tag == "ary")
+        return "ar";
+    if (tag == "arz")
+        return "ar";
+    if (tag == "ase")
+        return "sgn";
+    if (tag == "asf")
+        return "sgn";
+    if (tag == "asp")
+        return "sgn";
+    if (tag == "asq")
+        return "sgn";
+    if (tag == "asw")
+        return "sgn";
+    if (tag == "auz")
+        return "ar";
+    if (tag == "avl")
+        return "ar";
+    if (tag == "ayh")
+        return "ar";
+    if (tag == "ayl")
+        return "ar";
+    if (tag == "ayn")
+        return "ar";
+    if (tag == "ayp")
+        return "ar";
+    if (tag == "bbz")
+        return "ar";
+    if (tag == "bfi")
+        return "sgn";
+    if (tag == "bfk")
+        return "sgn";
+    if (tag == "bjn")
+        return "ms";
+    if (tag == "bog")
+        return "sgn";
+    if (tag == "bqn")
+        return "sgn";
+    if (tag == "bqy")
+        return "sgn";
+    if (tag == "btj")
+        return "ms";
+    if (tag == "bve")
+        return "ms";
+    if (tag == "bvl")
+        return "sgn";
+    if (tag == "bvu")
+        return "ms";
+    if (tag == "bzs")
+        return "sgn";
+    if (tag == "cdo")
+        return "zh";
+    if (tag == "cds")
+        return "sgn";
+    if (tag == "cjy")
+        return "zh";
+    if (tag == "cmn")
+        return "zh";
+    if (tag == "coa")
+        return "ms";
+    if (tag == "cpx")
+        return "zh";
+    if (tag == "csc")
+        return "sgn";
+    if (tag == "csd")
+        return "sgn";
+    if (tag == "cse")
+        return "sgn";
+    if (tag == "csf")
+        return "sgn";
+    if (tag == "csg")
+        return "sgn";
+    if (tag == "csl")
+        return "sgn";
+    if (tag == "csn")
+        return "sgn";
+    if (tag == "csq")
+        return "sgn";
+    if (tag == "csr")
+        return "sgn";
+    if (tag == "czh")
+        return "zh";
+    if (tag == "czo")
+        return "zh";
+    if (tag == "doq")
+        return "sgn";
+    if (tag == "dse")
+        return "sgn";
+    if (tag == "dsl")
+        return "sgn";
+    if (tag == "dup")
+        return "ms";
+    if (tag == "ecs")
+        return "sgn";
+    if (tag == "esl")
+        return "sgn";
+    if (tag == "esn")
+        return "sgn";
+    if (tag == "eso")
+        return "sgn";
+    if (tag == "eth")
+        return "sgn";
+    if (tag == "fcs")
+        return "sgn";
+    if (tag == "fse")
+        return "sgn";
+    if (tag == "fsl")
+        return "sgn";
+    if (tag == "fss")
+        return "sgn";
+    if (tag == "gan")
+        return "zh";
+    if (tag == "gds")
+        return "sgn";
+    if (tag == "gom")
+        return "kok";
+    if (tag == "gse")
+        return "sgn";
+    if (tag == "gsg")
+        return "sgn";
+    if (tag == "gsm")
+        return "sgn";
+    if (tag == "gss")
+        return "sgn";
+    if (tag == "gus")
+        return "sgn";
+    if (tag == "hab")
+        return "sgn";
+    if (tag == "haf")
+        return "sgn";
+    if (tag == "hak")
+        return "zh";
+    if (tag == "hds")
+        return "sgn";
+    if (tag == "hji")
+        return "ms";
+    if (tag == "hks")
+        return "sgn";
+    if (tag == "hos")
+        return "sgn";
+    if (tag == "hps")
+        return "sgn";
+    if (tag == "hsh")
+        return "sgn";
+    if (tag == "hsl")
+        return "sgn";
+    if (tag == "hsn")
+        return "zh";
+    if (tag == "icl")
+        return "sgn";
+    if (tag == "iks")
+        return "sgn";
+    if (tag == "ils")
+        return "sgn";
+    if (tag == "inl")
+        return "sgn";
+    if (tag == "ins")
+        return "sgn";
+    if (tag == "ise")
+        return "sgn";
+    if (tag == "isg")
+        return "sgn";
+    if (tag == "isr")
+        return "sgn";
+    if (tag == "jak")
+        return "ms";
+    if (tag == "jax")
+        return "ms";
+    if (tag == "jcs")
+        return "sgn";
+    if (tag == "jhs")
+        return "sgn";
+    if (tag == "jls")
+        return "sgn";
+    if (tag == "jos")
+        return "sgn";
+    if (tag == "jsl")
+        return "sgn";
+    if (tag == "jus")
+        return "sgn";
+    if (tag == "kgi")
+        return "sgn";
+    if (tag == "knn")
+        return "kok";
+    if (tag == "kvb")
+        return "ms";
+    if (tag == "kvk")
+        return "sgn";
+    if (tag == "kvr")
+        return "ms";
+    if (tag == "kxd")
+        return "ms";
+    if (tag == "lbs")
+        return "sgn";
+    if (tag == "lce")
+        return "ms";
+    if (tag == "lcf")
+        return "ms";
+    if (tag == "liw")
+        return "ms";
+    if (tag == "lls")
+        return "sgn";
+    if (tag == "lsg")
+        return "sgn";
+    if (tag == "lsl")
+        return "sgn";
+    if (tag == "lso")
+        return "sgn";
+    if (tag == "lsp")
+        return "sgn";
+    if (tag == "lst")
+        return "sgn";
+    if (tag == "lsy")
+        return "sgn";
+    if (tag == "ltg")
+        return "lv";
+    if (tag == "lvs")
+        return "lv";
+    if (tag == "lws")
+        return "sgn";
+    if (tag == "lzh")
+        return "zh";
+    if (tag == "max")
+        return "ms";
+    if (tag == "mdl")
+        return "sgn";
+    if (tag == "meo")
+        return "ms";
+    if (tag == "mfa")
+        return "ms";
+    if (tag == "mfb")
+        return "ms";
+    if (tag == "mfs")
+        return "sgn";
+    if (tag == "min")
+        return "ms";
+    if (tag == "mnp")
+        return "zh";
+    if (tag == "mqg")
+        return "ms";
+    if (tag == "mre")
+        return "sgn";
+    if (tag == "msd")
+        return "sgn";
+    if (tag == "msi")
+        return "ms";
+    if (tag == "msr")
+        return "sgn";
+    if (tag == "mui")
+        return "ms";
+    if (tag == "mzc")
+        return "sgn";
+    if (tag == "mzg")
+        return "sgn";
+    if (tag == "mzy")
+        return "sgn";
+    if (tag == "nan")
+        return "zh";
+    if (tag == "nbs")
+        return "sgn";
+    if (tag == "ncs")
+        return "sgn";
+    if (tag == "nsi")
+        return "sgn";
+    if (tag == "nsl")
+        return "sgn";
+    if (tag == "nsp")
+        return "sgn";
+    if (tag == "nsr")
+        return "sgn";
+    if (tag == "nzs")
+        return "sgn";
+    if (tag == "okl")
+        return "sgn";
+    if (tag == "orn")
+        return "ms";
+    if (tag == "ors")
+        return "ms";
+    if (tag == "pel")
+        return "ms";
+    if (tag == "pga")
+        return "ar";
+    if (tag == "pgz")
+        return "sgn";
+    if (tag == "pks")
+        return "sgn";
+    if (tag == "prl")
+        return "sgn";
+    if (tag == "prz")
+        return "sgn";
+    if (tag == "psc")
+        return "sgn";
+    if (tag == "psd")
+        return "sgn";
+    if (tag == "pse")
+        return "ms";
+    if (tag == "psg")
+        return "sgn";
+    if (tag == "psl")
+        return "sgn";
+    if (tag == "pso")
+        return "sgn";
+    if (tag == "psp")
+        return "sgn";
+    if (tag == "psr")
+        return "sgn";
+    if (tag == "pys")
+        return "sgn";
+    if (tag == "rms")
+        return "sgn";
+    if (tag == "rsi")
+        return "sgn";
+    if (tag == "rsl")
+        return "sgn";
+    if (tag == "rsm")
+        return "sgn";
+    if (tag == "sdl")
+        return "sgn";
+    if (tag == "sfb")
+        return "sgn";
+    if (tag == "sfs")
+        return "sgn";
+    if (tag == "sgg")
+        return "sgn";
+    if (tag == "sgx")
+        return "sgn";
+    if (tag == "shu")
+        return "ar";
+    if (tag == "slf")
+        return "sgn";
+    if (tag == "sls")
+        return "sgn";
+    if (tag == "sqk")
+        return "sgn";
+    if (tag == "sqs")
+        return "sgn";
+    if (tag == "ssh")
+        return "ar";
+    if (tag == "ssp")
+        return "sgn";
+    if (tag == "ssr")
+        return "sgn";
+    if (tag == "svk")
+        return "sgn";
+    if (tag == "swc")
+        return "sw";
+    if (tag == "swh")
+        return "sw";
+    if (tag == "swl")
+        return "sgn";
+    if (tag == "syy")
+        return "sgn";
+    if (tag == "szs")
+        return "sgn";
+    if (tag == "tmw")
+        return "ms";
+    if (tag == "tse")
+        return "sgn";
+    if (tag == "tsm")
+        return "sgn";
+    if (tag == "tsq")
+        return "sgn";
+    if (tag == "tss")
+        return "sgn";
+    if (tag == "tsy")
+        return "sgn";
+    if (tag == "tza")
+        return "sgn";
+    if (tag == "ugn")
+        return "sgn";
+    if (tag == "ugy")
+        return "sgn";
+    if (tag == "ukl")
+        return "sgn";
+    if (tag == "uks")
+        return "sgn";
+    if (tag == "urk")
+        return "ms";
+    if (tag == "uzn")
+        return "uz";
+    if (tag == "uzs")
+        return "uz";
+    if (tag == "vgt")
+        return "sgn";
+    if (tag == "vkk")
+        return "ms";
+    if (tag == "vkt")
+        return "ms";
+    if (tag == "vsi")
+        return "sgn";
+    if (tag == "vsl")
+        return "sgn";
+    if (tag == "vsv")
+        return "sgn";
+    if (tag == "wbs")
+        return "sgn";
+    if (tag == "wuu")
+        return "zh";
+    if (tag == "xki")
+        return "sgn";
+    if (tag == "xml")
+        return "sgn";
+    if (tag == "xmm")
+        return "ms";
+    if (tag == "xms")
+        return "sgn";
+    if (tag == "yds")
+        return "sgn";
+    if (tag == "ygs")
+        return "sgn";
+    if (tag == "yhs")
+        return "sgn";
+    if (tag == "ysl")
+        return "sgn";
+    if (tag == "yue")
+        return "zh";
+    if (tag == "zib")
+        return "sgn";
+    if (tag == "zlm")
+        return "ms";
+    if (tag == "zmi")
+        return "ms";
+    if (tag == "zsl")
+        return "sgn";
+    if (tag == "zsm")
+        return "ms";
+    return "";
+}
+
+static std::string intlPreferredRegionTag(const std::string& tag)
+{
+    // 6 possible replacements
+    if (tag == "BU")
+        return "MM";
+    if (tag == "DD")
+        return "DE";
+    if (tag == "FX")
+        return "FR";
+    if (tag == "TP")
+        return "TL";
+    if (tag == "YD")
+        return "YE";
+    if (tag == "ZR")
+        return "CD";
+    return "";
+}
+
+static std::string preferredRegion(const std::string& region)
+{
+    auto preferred = intlPreferredRegionTag(region);
+    if (preferred != "") {
+        return preferred;
+    }
+    return region;
+}
+
+static std::string privateUseLangTag(const std::vector<std::string>& parts, size_t startIndex)
+{
+    size_t numParts = parts.size();
+    size_t currentIndex = startIndex;
+
+    // Check for privateuse.
+    // privateuse = "x" 1*("-" (2*8alphanum))
+    StringBuilder privateuse;
+    while (currentIndex < numParts) {
+        std::string singleton = parts[currentIndex];
+        unsigned singletonLength = singleton.length();
+        bool isValid = (singletonLength == 1 && (singleton == "x" || singleton == "X"));
+        if (!isValid)
+            break;
+
+        if (currentIndex != startIndex)
+            privateuse.appendChar('-');
+
+        ++currentIndex;
+        unsigned numExtParts = 0;
+        privateuse.appendChar('x');
+        while (currentIndex < numParts) {
+            std::string extPart = parts[currentIndex];
+            unsigned extPartLength = extPart.length();
+
+            bool isValid = (extPartLength >= 1 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
+            if (!isValid)
+                break;
+
+            ++currentIndex;
+            ++numExtParts;
+            privateuse.appendChar('-');
+            std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
+            privateuse.appendString(String::fromUTF8(extPart.data(), extPart.length()));
+        }
+
+        // Requires at least one production.
+        if (!numExtParts)
+            return std::string();
+    }
+
+    // Leftovers makes it invalid.
+    if (currentIndex < numParts)
+        return std::string();
+
+    return privateuse.finalize()->toNonGCUTF8StringData();
+}
+
+Intl::CanonicalizedLangunageTag Intl::canonicalizeLanguageTag(const std::string& locale, const std::string& unicodeExtensionNameShouldIgnored)
+{
+    std::vector<std::string> parts = split(locale, '-');
+
+    Intl::CanonicalizedLangunageTag result;
+
+    // Follows the grammar at https://www.rfc-editor.org/rfc/bcp/bcp47.txt
+    // langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]
+    size_t numParts = parts.size();
+    // Check for language.
+    // language = 2*3ALPHA ["-" extlang] / 4ALPHA (reserved) / 5*8ALPHA
+    size_t currentIndex = 0;
+    std::string language = parts[currentIndex];
+    unsigned languageLength = language.length();
+    bool canHaveExtlang = languageLength >= 2 && languageLength <= 3;
+    bool isValidLanguage = languageLength != 4 && languageLength >= 2 && languageLength <= 8 && isAllSpecialCharacters(language, isASCIIAlpha);
+    if (!isValidLanguage) {
+        return Intl::CanonicalizedLangunageTag();
+    }
+
+    ++currentIndex;
+    StringBuilder canonical;
+
+    std::transform(language.begin(), language.end(), language.begin(), tolower);
+    result.language = language;
+    language = Intl::preferredLanguage(language);
+    canonical.appendString(String::fromUTF8(language.data(), language.length()));
+
+    // Check for extlang.
+    // extlang = 3ALPHA *2("-" 3ALPHA)
+    if (canHaveExtlang) {
+        for (unsigned times = 0; times < 3 && currentIndex < numParts; ++times) {
+            std::string extlang = parts[currentIndex];
+            unsigned extlangLength = extlang.length();
+            if (extlangLength == 3 && isAllSpecialCharacters(extlang, isASCIIAlpha)) {
+                ++currentIndex;
+                std::transform(extlang.begin(), extlang.end(), extlang.begin(), tolower);
+                result.extLang.push_back(extlang);
+                if (!times && intlPreferredExtlangTag(extlang) == language) {
+                    canonical.clear();
+                    canonical.appendString(String::fromUTF8(extlang.data(), extlang.length()));
+                    continue;
+                }
+                canonical.appendString("-");
+                canonical.appendString(String::fromUTF8(extlang.data(), extlang.length()));
+            } else {
+                break;
+            }
+        }
+    }
+
+    // Check for script.
+    // script = 4ALPHA
+    if (currentIndex < numParts) {
+        std::string script = parts[currentIndex];
+        unsigned scriptLength = script.length();
+        if (scriptLength == 4 && isAllSpecialCharacters(script, isASCIIAlpha)) {
+            ++currentIndex;
+            canonical.appendString("-");
+            std::transform(script.begin(), script.end(), script.begin(), tolower);
+            result.script += (char)toupper(script[0]);
+            canonical.appendChar((char)toupper(script[0]));
+            script = script.substr(1, 3);
+            result.script += script;
+            canonical.appendString(String::fromUTF8(script.data(), script.length()));
+        }
+    }
+
+    // Check for region.
+    // region = 2ALPHA / 3DIGIT
+    if (currentIndex < numParts) {
+        std::string region = parts[currentIndex];
+        unsigned regionLength = region.length();
+        bool isValidRegion = ((regionLength == 2 && isAllSpecialCharacters(region, isASCIIAlpha))
+                              || (regionLength == 3 && isAllSpecialCharacters(region, isASCIIDigit)));
+        if (isValidRegion) {
+            ++currentIndex;
+            canonical.appendChar('-');
+            std::transform(region.begin(), region.end(), region.begin(), toupper);
+            result.region = region;
+            auto preffered = preferredRegion(region);
+            canonical.appendString(String::fromUTF8(preffered.data(), preffered.length()));
+        }
+    }
+
+    // Check for variant.
+    // variant = 5*8alphanum / (DIGIT 3alphanum)
+    std::unordered_set<std::string> subtags;
+    while (currentIndex < numParts) {
+        std::string variant = parts[currentIndex];
+        unsigned variantLength = variant.length();
+        bool isValidVariant = ((variantLength >= 5 && variantLength <= 8 && isAllSpecialCharacters(variant, isASCIIAlphanumeric))
+                               || (variantLength == 4 && isASCIIDigit(variant[0]) && isAllSpecialCharacters(variant.substr(1, 3), isASCIIAlphanumeric)));
+        if (!isValidVariant) {
+            break;
+        }
+
+        // Cannot include duplicate subtags (case insensitive).
+        std::string lowerVariant = variant;
+        std::transform(lowerVariant.begin(), lowerVariant.end(), lowerVariant.begin(), tolower);
+        auto iter = subtags.find(lowerVariant);
+        if (iter != subtags.end()) {
+            return Intl::CanonicalizedLangunageTag();
+        }
+        subtags.insert(lowerVariant);
+
+        ++currentIndex;
+
+        result.variant.push_back(lowerVariant);
+    }
+
+    std::sort(result.variant.begin(), result.variant.end());
+    for (size_t i = 0; i < result.variant.size(); i++) {
+        canonical.appendChar('-');
+        canonical.appendString(result.variant[i].data());
+    }
+
+    // Check for extension.
+    // extension = singleton 1*("-" (2*8alphanum))
+    // singleton = alphanum except x or X
+    subtags.clear();
+    while (currentIndex < numParts) {
+        std::string possibleSingleton = parts[currentIndex];
+        unsigned singletonLength = possibleSingleton.length();
+        bool isValidSingleton = (singletonLength == 1 && possibleSingleton != "x" && possibleSingleton != "X" && isASCIIAlphanumeric(possibleSingleton[0]));
+        if (!isValidSingleton) {
+            break;
+        }
+
+        // Cannot include duplicate singleton (case insensitive).
+        std::string singleton = possibleSingleton;
+        std::transform(possibleSingleton.begin(), possibleSingleton.end(), possibleSingleton.begin(), tolower);
+
+        auto iter = subtags.find(singleton);
+        if (iter != subtags.end()) {
+            return Intl::CanonicalizedLangunageTag();
+        }
+        subtags.insert(singleton);
+
+        Intl::CanonicalizedLangunageTag::ExtensionSingleton singletonValue;
+        singletonValue.key = possibleSingleton[0];
+
+        ++currentIndex;
+
+        bool unicodeExtensionIgnored = false;
+        if (singletonValue.key == 'u') {
+            // "u" needs ordered key, value
+            // "u" doesn't allow single "true" as value
+
+            std::vector<std::pair<std::string, std::vector<std::string>>> values;
+
+            std::string key;
+            std::vector<std::string> value;
+
+            while (currentIndex < numParts) {
+                std::string extPart = parts[currentIndex];
+                unsigned extPartLength = extPart.length();
+
+                bool isValid = (extPartLength >= 2 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
+                if (!isValid) {
+                    break;
+                }
+
+                ++currentIndex;
+                std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
+
+                if (extPartLength == 2) {
+                    if (key.length() || value.size()) {
+                        if (key.length() && value.size() == 1 && value[0] == "true") {
+                            value.clear();
+                        }
+                        values.push_back(std::make_pair(key, value));
+                        key.clear();
+                        value.clear();
+                    }
+                    key = extPart;
+                } else {
+                    value.push_back(extPart);
+                }
+            }
+
+            bool unicodeExtensionIgnoredOnce = (key.length() && key == unicodeExtensionNameShouldIgnored);
+            unicodeExtensionIgnored |= unicodeExtensionIgnoredOnce;
+
+            if (!unicodeExtensionIgnoredOnce && (key.length() || value.size())) {
+                if (key.length() && value.size() == 1 && value[0] == "true") {
+                    value.clear();
+                }
+                values.push_back(std::make_pair(key, value));
+                key.clear();
+                value.clear();
+            }
+
+            std::sort(values.begin(), values.end(),
+                      [](const std::pair<std::string, std::vector<std::string>>& a, const std::pair<std::string, std::vector<std::string>>& b) -> bool {
+                          return a.first < b.first;
+                      });
+
+            // Attributes in Unicode extensions are reordered in US-ASCII order.
+            if (values.size() && !values.begin()->first.length()) {
+                std::sort(values.begin()->second.begin(), values.begin()->second.end());
+            }
+
+            std::string resultValue;
+            for (size_t i = 0; i < values.size(); i++) {
+                if (values[i].first.size()) {
+                    if (resultValue.size()) {
+                        resultValue += '-';
+                    }
+                    resultValue += values[i].first;
+                }
+
+                for (size_t j = 0; j < values[i].second.size(); j++) {
+                    if (resultValue.size()) {
+                        resultValue += '-';
+                    }
+                    resultValue += values[i].second[j];
+                }
+            }
+
+            singletonValue.value = std::move(resultValue);
+
+            std::vector<std::pair<std::string, std::string>> unicodeExtensionValue;
+
+            for (size_t i = 0; i < values.size(); i++) {
+                std::string singleUnicodeExtensionValue;
+                for (size_t j = 0; j < values[i].second.size(); j++) {
+                    if (singleUnicodeExtensionValue.length()) {
+                        singleUnicodeExtensionValue += '-';
+                    }
+                    singleUnicodeExtensionValue += values[i].second[j];
+                }
+                unicodeExtensionValue.push_back(std::make_pair(values[i].first, singleUnicodeExtensionValue));
+            }
+
+            result.unicodeExtension = std::move(unicodeExtensionValue);
+
+            if (unicodeExtensionIgnored && !result.unicodeExtension.size()) {
+                continue;
+            }
+        } else {
+            std::string single;
+            while (currentIndex < numParts) {
+                std::string extPart = parts[currentIndex];
+                unsigned extPartLength = extPart.length();
+
+                bool isValid = (extPartLength >= 2 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
+                if (!isValid) {
+                    break;
+                }
+
+                ++currentIndex;
+                std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
+
+                if (single.length()) {
+                    single += '-';
+                }
+                single += extPart;
+            }
+
+            singletonValue.value = std::move(single);
+        }
+
+        result.extensions.push_back(singletonValue);
+
+        // Requires at least one production.
+        if (!result.extensions.back().value.size()) {
+            return Intl::CanonicalizedLangunageTag();
+        }
+    }
+
+    // Add extensions to canonical sorted by singleton.
+    std::sort(result.extensions.begin(), result.extensions.end(),
+              [](const Intl::CanonicalizedLangunageTag::ExtensionSingleton& a, const Intl::CanonicalizedLangunageTag::ExtensionSingleton& b) -> bool {
+                  return a.key < b.key;
+              });
+    size_t numExtenstions = result.extensions.size();
+    for (size_t i = 0; i < numExtenstions; ++i) {
+        canonical.appendChar('-');
+        canonical.appendChar(result.extensions[i].key);
+        canonical.appendChar('-');
+        canonical.appendString(String::fromUTF8(result.extensions[i].value.data(), result.extensions[i].value.length()));
+    }
+
+    // Check for privateuse.
+    if (currentIndex < numParts) {
+        std::string privateUse = privateUseLangTag(parts, currentIndex);
+        if (privateUse.length() == 0) {
+            return Intl::CanonicalizedLangunageTag();
+        }
+        canonical.appendChar('-');
+        canonical.appendString(String::fromUTF8(privateUse.data(), privateUse.length()));
+        result.privateUse = privateUse;
+    }
+
+    String* e = canonical.finalize();
+    auto estd = e->toNonGCUTF8StringData();
+    auto preferred = intlRedundantLanguageTag(estd);
+    if (preferred != "") {
+        e = String::fromUTF8(preferred.data(), preferred.length());
+    }
+
+    result.canonicalizedTag = e;
+    return result;
+}
+
+Intl::CanonicalizedLangunageTag Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(const std::string& locale)
+{
+    if (isValidTagInBCP47ButInvalidOnUTS35(locale)) {
+        return Intl::CanonicalizedLangunageTag();
+    }
+    std::string grandfather = grandfatheredLangTag(locale);
+    if (grandfather.length()) {
+        return canonicalizeLanguageTag(grandfather);
+    }
+
+    return canonicalizeLanguageTag(locale);
+}
+
+String* Intl::icuLocaleToBCP47Tag(String* string)
+{
+    StringBuilder sb;
+    for (size_t i = 0; i < string->length(); i++) {
+        char16_t ch = string->charAt(i);
+        if (ch == '_')
+            ch = '-';
+        sb.appendChar(ch);
+    }
+    return sb.finalize();
+}
+
+static String* defaultLocale(ExecutionState& state)
+{
+    String* localeString = String::fromUTF8(state.context()->vmInstance()->locale().data(), state.context()->vmInstance()->locale().length());
+    return Intl::icuLocaleToBCP47Tag(localeString);
+}
+
+static String* removeUnicodeLocaleExtension(ExecutionState& state, String* locale)
+{
+    auto utf8 = locale->toUTF8StringData();
+    std::string stdUTF8(utf8.data(), utf8.length());
+    std::vector<std::string> parts = split(stdUTF8, '-');
+
+    StringBuilder builder;
+    size_t partsSize = parts.size();
+    if (partsSize > 0)
+        builder.appendString(String::fromUTF8(parts[0].data(), parts[0].size()));
+    for (size_t p = 1; p < partsSize; ++p) {
+        if (parts[p] == "u") {
+            // Skip the u- and anything that follows until another singleton.
+            // While the next part is part of the unicode extension, skip it.
+            while (p + 1 < partsSize && parts[p + 1].length() > 1)
+                ++p;
+        } else {
+            builder.appendChar('-');
+            builder.appendString(String::fromUTF8(parts[p].data(), parts[p].size()));
+        }
+    }
+    return builder.finalize();
+}
+
+ValueVector Intl::canonicalizeLocaleList(ExecutionState& state, Value locales)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.1
+    // If locales is undefined, then
+    if (locales.isUndefined()) {
+        // Return a new empty List.
+        return ValueVector();
+    }
+    // Let seen be a new empty List.
+    ValueVector seen;
+
+    Object* O;
+    // If Type(locales) is String or locales has an [[InitializedLocale]] internal slot, then
+    if (locales.isString() || (locales.isObject() && locales.asObject()->isIntlLocaleObject())) {
+        // Let O be CreateArrayFromList(« locales »).
+        ValueVector vv;
+        vv.push_back(locales);
+        O = Object::createArrayFromList(state, vv);
+    } else {
+        // Else
+        // Let O be ToObject(locales).
+        O = locales.toObject(state);
+    }
+
+    uint64_t len = O->length(state);
+    // Let k be 0.
+    // Repeat, while k < len
+    uint64_t k = 0;
+    while (k < len) {
+        // Let Pk be ToString(k).
+        ObjectPropertyName pk(state, Value(k));
+        ObjectHasPropertyResult pkResult = O->hasProperty(state, pk);
+        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
+        // If kPresent is true, then
+        if (pkResult.hasProperty()) {
+            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
+            Value kValue = pkResult.value(state, pk, O);
+            // If the type of kValue is not String or Object, then throw a TypeError exception.
+            if (!kValue.isString() && !kValue.isObject()) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Type of element of locales must be String or Object");
+            }
+
+            String* tag;
+            // If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
+            if (kValue.isObject() && kValue.asObject()->isIntlLocaleObject()) {
+                // Let tag be kValue.[[Locale]].
+                tag = kValue.asObject()->asIntlLocaleObject()->locale();
+            } else {
+                // Else,
+                // Let tag be ToString(kValue).
+                tag = kValue.toString(state);
+            }
+            // If the result of calling the abstract operation IsStructurallyValidLanguageTag (defined in 6.2.2), passing tag as the argument,
+            // is false, then throw a RangeError exception.
+            // Let tag be the result of calling the abstract operation CanonicalizeLanguageTag (defined in 6.2.3), passing tag as the argument.
+            // If tag is not an element of seen, then append tag as the last element of seen.
+            auto canonicalizedTag = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(tag->toNonGCUTF8StringData());
+            if (!canonicalizedTag.canonicalizedTag) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got Invalid locale");
+            }
+            tag = canonicalizedTag.canonicalizedTag.value();
+            bool has = false;
+            for (size_t i = 0; i < seen.size(); i++) {
+                if (seen[i].equalsTo(state, tag)) {
+                    has = true;
+                    break;
+                }
+            }
+            if (!has) {
+                seen.pushBack(tag);
+            }
+
+            // Increase k by 1.
+            k++;
+        } else {
+            // Increase k by 1.
+            int64_t nextIndex;
+            Object::nextIndexForward(state, O, k, len, nextIndex);
+            k = nextIndex;
+        }
+    }
+
+    // Return seen.
+    return seen;
+}
+
+static String* bestAvailableLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, Value locale)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.2
+    // Let candidate be locale.
+    String* candidate = locale.toString(state);
+
+    // Repeat
+    while (candidate->length()) {
+        // If availableLocales contains an element equal to candidate, then return candidate.
+        bool contains = false;
+        for (size_t i = 0; i < availableLocales.size(); i++) {
+            if (availableLocales[i]->equals(candidate)) {
+                contains = true;
+                break;
+            }
+        }
+
+        if (contains)
+            return candidate;
+
+        // Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. If that character does not occur, return undefined.
+        size_t pos = candidate->rfind(state.context()->staticStrings().asciiTable[(size_t)'-'].string(), candidate->length() - 1);
+        if (pos == SIZE_MAX)
+            return String::emptyString;
+
+        // If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, then decrease pos by 2.
+        if (pos >= 2 && candidate->charAt(pos - 2) == '-')
+            pos -= 2;
+
+        // d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
+        candidate = candidate->substring(0, pos);
+    }
+
+    return String::emptyString;
+}
+
+static Intl::IntlMatcherResult lookupMatcher(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>> availableLocales, const ValueVector& requestedLocales)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.3
+    // Let i be 0.
+    size_t i = 0;
+    // Let len be the number of elements in requestedLocales.
+    size_t len = requestedLocales.size();
+    // Let availableLocale be undefined.
+    String* availableLocale = String::emptyString;
+
+    String* locale = String::emptyString;
+    String* noExtensionsLocale = String::emptyString;
+
+    // Repeat while i < len and availableLocale is undefined:
+    while (i < len && availableLocale->length() == 0) {
+        // Let locale be the element of requestedLocales at 0-origined list position i.
+        locale = requestedLocales[i].toString(state);
+        // Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
+        noExtensionsLocale = removeUnicodeLocaleExtension(state, locale);
+        // Let availableLocale be the result of calling the BestAvailableLocale abstract operation (defined in 9.2.2) with arguments availableLocales and noExtensionsLocale.
+        availableLocale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
+        // Increase i by 1.
+        i++;
+    }
+
+    // Let result be a new Record.
+    Intl::IntlMatcherResult result;
+
+    // If availableLocale is not undefined, then
+    if (availableLocale->length()) {
+        // Set result.[[locale]] to availableLocale.
+        result.locale = availableLocale;
+        // If locale and noExtensionsLocale are not the same String value, then
+        if (!locale->equals(noExtensionsLocale)) {
+            // Let extension be the String value consisting of the first substring of locale that is a Unicode locale extension sequence.
+            // Let extensionIndex be the character position of the initial "-" of the first Unicode locale extension sequence within locale.
+            // Set result.[[extension]] to extension.
+            // Set result.[[extensionIndex]] to extensionIndex.
+
+            bool unicodeExtensionExists = false;
+            if (locale->find("-x-") != SIZE_MAX) {
+                unicodeExtensionExists = true;
+            }
+
+            if (!unicodeExtensionExists) {
+                size_t extensionIndex = locale->find("-u-");
+                ASSERT(extensionIndex != SIZE_MAX);
+
+                size_t extensionLength = locale->length() - extensionIndex;
+                size_t end = extensionIndex + 3;
+                while (end < locale->length()) {
+                    end = locale->find("-", end);
+                    if (end == SIZE_MAX)
+                        break;
+                    if (end + 2 < locale->length() && locale->charAt(end + 2) == '-') {
+                        extensionLength = end - extensionIndex;
+                        break;
+                    }
+                    end++;
+                }
+                result.extension = locale->substring(extensionIndex, extensionIndex + extensionLength);
+                result.extensionIndex = extensionIndex;
+            }
+        }
+    } else {
+        // Set result.[[locale]] to the value returned by the DefaultLocale abstract operation (defined in 6.2.4).
+        result.locale = defaultLocale(state);
+    }
+
+    return result;
+}
+
+static Intl::IntlMatcherResult bestFitMatcher(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>> availableLocales, const ValueVector& requestedLocales)
+{
+    // TODO
+    return lookupMatcher(state, availableLocales, requestedLocales);
+}
+
+static Optional<String*> unicodeExtensionValue(ExecutionState& state, String* extension, const char* key)
+{
+    // Let size be the number of elements in extension.
+    auto size = extension->length();
+    // Let searchValue be the concatenation of "-", key, and "-".
+    StringBuilder searchValueBuilder;
+    searchValueBuilder.appendChar('-');
+    searchValueBuilder.appendString(key);
+    searchValueBuilder.appendChar('-');
+    String* searchValue = searchValueBuilder.finalize();
+
+    // Let pos be Call(%StringProto_indexOf%, extension, « searchValue »).
+    size_t pos = extension->find(searchValue);
+
+    // If pos ≠ -1, then
+    if (pos != SIZE_MAX) {
+        // Let start be pos + 4.
+        size_t start = pos + 4;
+        // Let end be start.
+        size_t end = start;
+        // Let k be start.
+        size_t k = start;
+        // Let done be false.
+        bool done = false;
+
+        // Repeat, while done is false
+        while (!done) {
+            // Let e be Call(%StringProto_indexOf%, extension, « "-", k »).
+            size_t e = extension->find("-", k);
+            size_t len;
+            // If e = -1,
+            if (e == SIZE_MAX) {
+                // let len be size - k;
+                len = size - k;
+            } else {
+                // else let len be e - k.
+                len = e - k;
+            }
+
+            // If len = 2, then
+            if (len == 2) {
+                // Let done be true.
+                done = true;
+            } else if (e == SIZE_MAX) {
+                // Else if e = -1, then
+                // Let end be size.
+                end = size;
+                // Let done be true.
+                done = true;
+            } else {
+                // Else,
+                // Let end be e.
+                end = e;
+                // Let k be e + 1.
+                k = e + 1;
+            }
+        }
+
+        // Return the String value equal to the substring of extension
+        // consisting of the code units at indices start (inclusive) through end (exclusive).
+        return extension->substring(start, end);
+    }
+
+    // Let searchValue be the concatenation of "-" and key.
+    searchValueBuilder.appendChar('-');
+    searchValueBuilder.appendString(key);
+    searchValue = searchValueBuilder.finalize();
+    // Let pos be Call(%StringProto_indexOf%, extension, « searchValue »).
+    pos = extension->find(searchValue);
+    // If pos ≠ -1 and pos + 3 = size, then
+    if (pos != SIZE_MAX && pos + 3 == size) {
+        return String::emptyString;
+    }
+
+    return nullptr;
+}
+
+
+static bool stringVectorContains(const std::vector<std::string>& v, const std::string& key)
+{
+    for (size_t j = 0; j < v.size(); j++) {
+        if (v[j] == key) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+StringMap Intl::resolveLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, const StringMap& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, LocaleDataImplFunction localeData)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-resolvelocale
+
+    // Let matcher be the value of options.[[localeMatcher]].
+    auto iter = options.find("localeMatcher");
+    Value matcher;
+    if (iter != options.end()) {
+        matcher = iter->second;
+    }
+
+    Intl::IntlMatcherResult r;
+    // If matcher is "lookup", then
+    if (matcher.equalsTo(state, state.context()->staticStrings().lazyLookup().string())) {
+        // Let r be LookupMatcher(availableLocales, requestedLocales).
+        r = lookupMatcher(state, availableLocales, requestedLocales);
+    } else {
+        // Else
+        // Let r be BestFitMatcher(availableLocales, requestedLocales).
+        r = bestFitMatcher(state, availableLocales, requestedLocales);
+    }
+
+    // Let foundLocale be the value of r.[[locale]].
+    String* foundLocale = r.locale;
+
+    // Let result be a new Record.
+    StringMap result;
+
+    // Set result.[[dataLocale]] to foundLocale.
+    result.insert(std::make_pair("dataLocale", foundLocale));
+
+    // Let supportedExtension be "-u".
+    String* supportedExtension = state.context()->staticStrings().lazyDashU().string();
+
+    // For each element key of relevantExtensionKeys in List order, do
+    size_t i = 0;
+    size_t len = relevantExtensionKeyCount;
+    while (i < len) {
+        const char* key = relevantExtensionKeys[i];
+        // Let foundLocaleData be localeData.[[<foundLocale>]].
+        // Let keyLocaleData be foundLocaleData.[[<key>]].
+        std::vector<std::string> keyLocaleData = localeData(foundLocale, i);
+        // Let value be keyLocaleData[0].
+        std::string value = keyLocaleData[0];
+
+        // Let supportedExtensionAddition be "".
+        String* supportedExtensionAddition = String::emptyString;
+
+        // If r has an [[extension]] field, then
+        if (r.extension->length()) {
+            // Let requestedValue be UnicodeExtensionValue(r.[[extension]], key).
+            Optional<String*> requestedValue = unicodeExtensionValue(state, r.extension, key);
+
+            // If requestedValue is not undefined, then
+            if (requestedValue) {
+                // If requestedValue is not the empty String, then
+                if (requestedValue.value()->length()) {
+                    // If keyLocaleData contains requestedValue, then
+                    if (stringVectorContains(keyLocaleData, requestedValue.value()->toNonGCUTF8StringData())) {
+                        // Let value be requestedValue.
+                        value = requestedValue.value()->toNonGCUTF8StringData();
+                        // Let supportedExtensionAddition be the concatenation of "-", key, "-", and value.
+                        StringBuilder supportedExtensionAdditionBuilder;
+                        supportedExtensionAdditionBuilder.appendChar('-');
+                        supportedExtensionAdditionBuilder.appendString(key);
+                        supportedExtensionAdditionBuilder.appendChar('-');
+                        supportedExtensionAdditionBuilder.appendString(value.data());
+                        supportedExtensionAddition = supportedExtensionAdditionBuilder.finalize();
+                    }
+                } else if (stringVectorContains(keyLocaleData, "true")) {
+                    // Else if keyLocaleData contains "true", then
+                    // Let value be "true".
+                    value = "true";
+                    // Let supportedExtensionAddition be the concatenation of "-" and key.
+                    StringBuilder supportedExtensionAdditionBuilder;
+                    supportedExtensionAdditionBuilder.appendChar('-');
+                    supportedExtensionAdditionBuilder.appendString(key);
+                    supportedExtensionAddition = supportedExtensionAdditionBuilder.finalize();
+                }
+            }
+        }
+
+        // If options has a field [[<key>]], then
+        if (options.find(key) != options.end()) {
+            // Let optionsValue be options.[[<key>]].
+            auto optionsValue = options.at(key);
+            // Assert: Type(optionsValue) is either String, Undefined, or Null.
+            // If keyLocaleData contains optionsValue, then
+            if (stringVectorContains(keyLocaleData, optionsValue->toNonGCUTF8StringData())) {
+                // If SameValue(optionsValue, value) is false, then
+                if (!optionsValue->equals(value.data(), value.length())) {
+                    // Let value be optionsValue.
+                    value = optionsValue->toNonGCUTF8StringData();
+                    // Let supportedExtensionAddition be "".
+                    supportedExtensionAddition = String::emptyString;
+                }
+            }
+        }
+
+        // Set result.[[<key>]] to value.
+        result.insert(std::make_pair(key, String::fromUTF8(value.data(), value.length())));
+
+        // Append supportedExtensionAddition to supportedExtension.
+        StringBuilder sb;
+        sb.appendString(supportedExtension);
+        sb.appendString(supportedExtensionAddition);
+        supportedExtension = sb.finalize();
+
+        i++;
+    }
+
+    // If the length of supportedExtension is greater than 2, then
+    if (supportedExtension->length() > 2) {
+        // Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »).
+        size_t privateIndex = foundLocale->find("-x-");
+
+        // If privateIndex = -1, then
+        if (privateIndex != SIZE_MAX) {
+            // Let foundLocale be the concatenation of foundLocale and supportedExtension.
+            StringBuilder sb;
+            sb.appendString(foundLocale);
+            sb.appendString(supportedExtension);
+            foundLocale = sb.finalize();
+        } else {
+            size_t len = foundLocale->length();
+            // Let preExtension be the substring of foundLocale from position 0, inclusive, to position extensionIndex, exclusive.
+            String* preExtension = foundLocale->substring(0, len > r.extensionIndex ? r.extensionIndex : len);
+
+            // Let postExtension be the substring of foundLocale from position extensionIndex to the end of the string.
+            String* postExtension = String::emptyString;
+            if (r.extensionIndex < len) {
+                postExtension = foundLocale->substring(r.extensionIndex, len);
+            }
+            // Let foundLocale be the concatenation of preExtension, supportedExtension, and postExtension.
+            StringBuilder sb;
+            sb.appendString(preExtension);
+            sb.appendString(supportedExtension);
+            sb.appendString(postExtension);
+            foundLocale = sb.finalize();
+        }
+
+        // Let foundLocale be CanonicalizeLanguageTag(foundLocale).
+        // Assert: IsStructurallyValidLanguageTag(foundLocale) is true.
+        foundLocale = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(foundLocale->toNonGCUTF8StringData()).canonicalizedTag.value();
+    }
+    // Set result.[[locale]] to foundLocale.
+    result.insert(std::make_pair("locale", foundLocale));
+    // Return result.
+    return result;
+}
+
+
+static ValueVector lookupSupportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.6
+    // Let len be the number of elements in requestedLocales.
+    size_t len = requestedLocales.size();
+    // Let subset be a new empty List.
+    ValueVector subset;
+    // Let k be 0.
+    size_t k = 0;
+    // Repeat while k < len
+    while (k < len) {
+        // Let locale be the element of requestedLocales at 0-origined list position k.
+        Value locale = requestedLocales[k];
+        // Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
+        String* noExtensionsLocale = removeUnicodeLocaleExtension(state, locale.toString(state));
+        // Let availableLocale be the result of calling the BestAvailableLocale abstract operation (defined in 9.2.2) with arguments availableLocales and noExtensionsLocale.
+        String* availableLocale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
+        // If availableLocale is not undefined, then append locale to the end of subset.
+        if (availableLocale->length()) {
+            subset.pushBack(locale);
+        }
+        // Increment k by 1.
+        k++;
+    }
+
+    return subset;
+}
+
+static ValueVector bestfitSupportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.7
+    // TODO
+    return lookupSupportedLocales(state, availableLocales, requestedLocales);
+}
+
+Value Intl::supportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, Value options)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.8
+    Value matcher;
+    // If options is not undefined, then
+    if (!options.isUndefined()) {
+        // Let options be ToObject(options).
+        options = options.toObject(state);
+        // Let matcher be the result of calling the [[Get]] internal method of options with argument "localeMatcher".
+        matcher = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyLocaleMatcher())).value(state, options.asObject());
+        // If matcher is not undefined, then
+        if (!matcher.isUndefined()) {
+            // Let matcher be ToString(matcher).
+            matcher = matcher.toString(state);
+            // If matcher is not "lookup" or "best fit", then throw a RangeError exception.
+            if (!(matcher.asString()->equals("lookup") || matcher.asString()->equals("best fit"))) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid value on options.localeMatcher");
+            }
+        }
+    }
+
+    // If matcher is undefined or "best fit", then
+    ValueVector subset;
+    if (matcher.isUndefined() || matcher.equalsTo(state, state.context()->staticStrings().lazyBestFit().string())) {
+        // Let subset be the result of calling the BestFitSupportedLocales abstract operation (defined in 9.2.7) with arguments availableLocales and requestedLocales.
+        subset = bestfitSupportedLocales(state, availableLocales, requestedLocales);
+    } else {
+        // Let subset be the result of calling the LookupSupportedLocales abstract operation (defined in 9.2.6) with arguments availableLocales and requestedLocales.
+        subset = lookupSupportedLocales(state, availableLocales, requestedLocales);
+    }
+
+    // Return CreateArrayFromList(supportedLocales).
+    return Object::createArrayFromList(state, subset);
+}
+
+Value Intl::getOption(ExecutionState& state, Object* options, Value property, Intl::OptionValueType type, Value* values, size_t valuesLength, const Value& fallback)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.9
+    // Let value be the result of calling the [[Get]] internal method of options with argument property.
+    Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
+    // If value is not undefined, then
+    if (!value.isUndefined()) {
+        // Assert: type is "boolean" or "string".
+        // If type is "boolean", then let value be ToBoolean(value).
+        if (type == Intl::OptionValueType::BooleanValue) {
+            value = Value(value.toBoolean(state));
+        }
+        // If type is "string", then let value be ToString(value).
+        if (type == Intl::OptionValueType::StringValue) {
+            value = Value(value.toString(state));
+        }
+        // If values is not undefined, then
+        if (valuesLength) {
+            // If values does not contain an element equal to value, then throw a RangeError exception.
+            bool contains = false;
+            for (size_t i = 0; i < valuesLength; i++) {
+                if (values[i].equalsTo(state, value)) {
+                    contains = true;
+                }
+            }
+            if (!contains) {
+                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid value");
+            }
+        }
+        // Return value.
+        return value;
+    } else {
+        // Else return fallback.
+        return fallback;
+    }
+}
+
+static std::vector<std::string> initAvailableNumberingSystems()
+{
+    std::vector<std::string> availableNumberingSystems;
+    UErrorCode status = U_ZERO_ERROR;
+    UEnumeration* numberingSystemNames = unumsys_openAvailableNames(&status);
+    ASSERT(U_SUCCESS(status));
+
+    int32_t resultLength;
+    // Numbering system names are always ASCII, so use char[].
+    while (const char* result = uenum_next(numberingSystemNames, &resultLength, &status)) {
+        ASSERT(U_SUCCESS(status));
+        auto numsys = unumsys_openByName(result, &status);
+        ASSERT(U_SUCCESS(status));
+        if (!unumsys_isAlgorithmic(numsys)) {
+            availableNumberingSystems.push_back(std::string(result, resultLength));
+        }
+        unumsys_close(numsys);
+    }
+    uenum_close(numberingSystemNames);
+
+    return availableNumberingSystems;
+}
+
+std::vector<std::string> Intl::numberingSystemsForLocale(String* locale)
+{
+    static std::vector<std::string> availableNumberingSystems = initAvailableNumberingSystems();
+
+    UErrorCode status = U_ZERO_ERROR;
+    UNumberingSystem* defaultSystem = unumsys_open(locale->toUTF8StringData().data(), &status);
+    ASSERT(U_SUCCESS(status));
+    std::string defaultSystemName(unumsys_getName(defaultSystem));
+    unumsys_close(defaultSystem);
+
+    std::vector<std::string> numberingSystems;
+    numberingSystems.push_back(defaultSystemName);
+    numberingSystems.insert(numberingSystems.end(), availableNumberingSystems.begin(), availableNumberingSystems.end());
+    return numberingSystems;
+}
+
+String* Intl::getLocaleForStringLocaleConvertCase(ExecutionState& state, Value locales)
+{
+    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+    // If requestedLocales is not an empty List, then
+    // a. Let requestedLocale be requestedLocales[0].
+    // Else Let requestedLocale be DefaultLocale().
+    String* requestedLocale = requestedLocales.size() > 0 ? requestedLocales[0].toString(state) : defaultLocale(state);
+    // Let noExtensionsLocale be the String value that is requestedLocale with all Unicode locale extension sequences (6.2.1) removed.
+    String* noExtensionsLocale = removeUnicodeLocaleExtension(state, requestedLocale);
+
+    // Let availableLocales be a List with language tags that includes the languages for which the Unicode Character Database contains language sensitive case mappings. Implementations may add additional language tags if they support case mapping for additional locales.
+    const auto& availableLocales = state.context()->vmInstance()->caseMappingAvailableLocales();
+    // Let locale be BestAvailableLocale(availableLocales, noExtensionsLocale).
+    String* locale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
+    return locale;
+}
+
+static bool is38Alphanum(const std::string& str)
+{
+    if (str.length() >= 3 && str.length() <= 8) {
+        return isAllSpecialCharacters(str, isASCIIAlphanumeric);
+    }
+    return false;
+}
+
+static bool is38AlphanumList(const std::string& str)
+{
+    std::size_t found = str.find("-");
+    if (found == std::string::npos) {
+        return is38Alphanum(str);
+    }
+    return is38Alphanum(str.substr(0, found)) && is38AlphanumList(str.substr(found + 1));
+}
+
+bool Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(String* value)
+{
+    return is38AlphanumList(value->toNonGCUTF8StringData());
+}
+
+void Intl::convertICUNumberFieldToEcmaNumberField(std::vector<NumberFieldItem>& fields, double x, const UTF16StringDataNonGCStd& resultString)
+{
+    // we need to divide integer field
+    // because icu returns result as
+    // 1.234 $
+    // "1.234" <- integer field
+    // but we want
+    // "1", "234"
+    std::vector<NumberFieldItem> integerFields;
+    for (size_t i = 0; i < fields.size(); i++) {
+        NumberFieldItem item = fields[i];
+
+        if (item.type == UNUM_INTEGER_FIELD) {
+            fields.erase(fields.begin() + i);
+            i--;
+
+            std::vector<std::pair<int32_t, int32_t>> apertures;
+
+            for (size_t j = 0; j < fields.size(); j++) {
+                if (fields[j].start >= item.start && fields[j].end <= item.end) {
+                    apertures.push_back(std::make_pair(fields[j].start, fields[j].end));
+                }
+            }
+            if (apertures.size()) {
+                NumberFieldItem newItem;
+                newItem.type = item.type;
+
+                int32_t lastStart = item.start;
+                for (size_t j = 0; j < apertures.size(); j++) {
+                    newItem.start = lastStart;
+                    newItem.end = apertures[j].first;
+                    integerFields.push_back(newItem);
+
+                    lastStart = apertures[j].second;
+                }
+
+                if (lastStart != item.end) {
+                    newItem.start = lastStart;
+                    newItem.end = item.end;
+                    integerFields.push_back(newItem);
+                }
+
+
+            } else {
+                integerFields.push_back(item);
+            }
+        }
+    }
+
+    fields.insert(fields.end(), integerFields.begin(), integerFields.end());
+
+    // add literal field if needs
+    if (!std::isnan(x) && !std::isinf(x)) {
+        std::vector<NumberFieldItem> literalFields;
+        for (size_t i = 0; i < resultString.length(); i++) {
+            bool found = false;
+            for (size_t j = 0; j < fields.size(); j++) {
+                if ((size_t)fields[j].start <= i && i < (size_t)fields[j].end) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                size_t end = i + 1;
+                while (end != resultString.length()) {
+                    bool found = false;
+                    for (size_t j = 0; j < fields.size(); j++) {
+                        if ((size_t)fields[j].start <= end && end < (size_t)fields[j].end) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    if (found) {
+                        break;
+                    }
+                    end++;
+                }
+
+                NumberFieldItem newItem;
+                newItem.type = -1;
+                newItem.start = i;
+                newItem.end = end;
+                i = end - 1;
+                literalFields.push_back(newItem);
+            }
+        }
+        fields.insert(fields.end(), literalFields.begin(), literalFields.end());
+    }
+
+    std::sort(fields.begin(), fields.end(),
+              [](const NumberFieldItem& a, const NumberFieldItem& b) -> bool {
+                  return a.start < b.start;
+              });
+}
+
+String* Intl::icuNumberFieldToString(ExecutionState& state, int32_t fieldName, double d)
+{
+    if (fieldName == -1) {
+        return state.context()->staticStrings().lazyLiteral().string();
+    }
+
+    switch ((UNumberFormatFields)fieldName) {
+    case UNUM_INTEGER_FIELD:
+        if (std::isnan(d)) {
+            return state.context()->staticStrings().lazySmallLetterNaN().string();
+        }
+        if (std::isinf(d)) {
+            return state.context()->staticStrings().lazySmallLetterInfinity().string();
+        }
+        return state.context()->staticStrings().lazyInteger().string();
+    case UNUM_GROUPING_SEPARATOR_FIELD:
+        return state.context()->staticStrings().lazyGroup().string();
+    case UNUM_DECIMAL_SEPARATOR_FIELD:
+        return state.context()->staticStrings().lazyDecimal().string();
+    case UNUM_FRACTION_FIELD:
+        return state.context()->staticStrings().lazyFraction().string();
+    case UNUM_SIGN_FIELD:
+        return std::signbit(d) ? state.context()->staticStrings().lazyMinusSign().string() : state.context()->staticStrings().lazyPlusSign().string();
+    case UNUM_PERCENT_FIELD:
+        return state.context()->staticStrings().lazyPercentSign().string();
+    case UNUM_CURRENCY_FIELD:
+        return state.context()->staticStrings().lazyCurrency().string();
+    case UNUM_EXPONENT_SYMBOL_FIELD:
+        return state.context()->staticStrings().lazyExponentSeparator().string();
+    case UNUM_EXPONENT_SIGN_FIELD:
+        return state.context()->staticStrings().lazyExponentMinusSign().string();
+    case UNUM_EXPONENT_FIELD:
+        return state.context()->staticStrings().lazyExponentInteger().string();
+    case UNUM_MEASURE_UNIT_FIELD:
+        return state.context()->staticStrings().lazyUnit().string();
+    case UNUM_COMPACT_FIELD:
+        return state.context()->staticStrings().lazyCompact().string();
+    default:
+        ASSERT_NOT_REACHED();
+        return String::emptyString;
+    }
+}
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.h b/lwnode/code/escargotshim/deps/escargot/src/intl/Intl.h
new file mode 100644 (file)
index 0000000..595bdce
--- /dev/null
@@ -0,0 +1,87 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotIntlObject__
+#define __EscargotIntlObject__
+
+namespace Escargot {
+
+class Intl {
+public:
+    typedef std::vector<std::string> (*LocaleDataImplFunction)(String* locale, size_t keyIndex);
+
+    struct IntlMatcherResult {
+        IntlMatcherResult()
+        {
+            extension = locale = String::emptyString;
+            extensionIndex = SIZE_MAX;
+        }
+
+        String* locale;
+        String* extension;
+        size_t extensionIndex;
+    };
+
+    static ValueVector canonicalizeLocaleList(ExecutionState& state, Value locales);
+    static StringMap resolveLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, const StringMap& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, LocaleDataImplFunction localeData);
+    static Value supportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, Value options);
+    enum OptionValueType {
+        StringValue,
+        BooleanValue
+    };
+    static Value getOption(ExecutionState& state, Object* options, Value property, OptionValueType type, Value* values, size_t valuesLength, const Value& fallback);
+    static std::string preferredLanguage(const std::string& language);
+    static String* icuLocaleToBCP47Tag(String* string);
+    static std::vector<std::string> calendarsForLocale(String* locale);
+    static std::vector<std::string> numberingSystemsForLocale(String* locale);
+    struct CanonicalizedLangunageTag {
+        Optional<String*> canonicalizedTag;
+        std::string language;
+        std::vector<std::string> extLang;
+        std::string script;
+        std::string region;
+        std::vector<std::string> variant;
+        struct ExtensionSingleton {
+            char key;
+            std::string value;
+        };
+        std::vector<ExtensionSingleton> extensions;
+        std::vector<std::pair<std::string, std::string>> unicodeExtension;
+        std::string privateUse;
+    };
+    static CanonicalizedLangunageTag canonicalizeLanguageTag(const std::string& locale, const std::string& unicodeExtensionNameShouldIgnored = "");
+    static CanonicalizedLangunageTag isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(const std::string& locale);
+    static String* getLocaleForStringLocaleConvertCase(ExecutionState& state, Value locales);
+
+    // test string is `(3*8alphanum) *("-" (3*8alphanum))` sequence
+    static bool isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(String* value);
+
+    struct NumberFieldItem {
+        int32_t start;
+        int32_t end;
+        int32_t type;
+    };
+    static void convertICUNumberFieldToEcmaNumberField(std::vector<NumberFieldItem>& fields, double x, const UTF16StringDataNonGCStd& resultString);
+    static String* icuNumberFieldToString(ExecutionState& state, int32_t fieldName, double d);
+};
+} // namespace Escargot
+
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.cpp
new file mode 100644 (file)
index 0000000..2cf2a9a
--- /dev/null
@@ -0,0 +1,454 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
+ * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "runtime/VMInstance.h"
+#include "Intl.h"
+#include "IntlCollator.h"
+
+namespace Escargot {
+
+static const char* const intlCollatorRelevantExtensionKeys[3] = { "co", "kn", "kf" };
+static const int intlCollatorRelevantExtensionKeysLength = 3;
+static const size_t indexOfExtensionKeyCo = 0;
+static const size_t indexOfExtensionKeyKn = 1;
+static const size_t indexOfExtensionKeyKf = 2;
+
+static std::vector<std::string> sortLocaleData(String* locale, size_t keyIndex)
+{
+    // 9.1 Internal slots of Service Constructors & 10.2.3 Internal slots (ECMA-402 2.0)
+    std::vector<std::string> keyLocaleData;
+    switch (keyIndex) {
+    case indexOfExtensionKeyCo: {
+        // 10.2.3 "The first element of [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co must be null for all locale values."
+        keyLocaleData.push_back(std::string());
+
+        UErrorCode status = U_ZERO_ERROR;
+
+        auto utf8 = locale->toUTF8StringData();
+        UEnumeration* enumeration = ucol_getKeywordValuesForLocale("collation", utf8.data(), false, &status);
+        if (U_SUCCESS(status)) {
+            const char* collation;
+            while ((collation = uenum_next(enumeration, nullptr, &status)) && U_SUCCESS(status)) {
+                // 10.2.3 "The values "standard" and "search" must not be used as elements in any [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co array."
+                if (!strcmp(collation, "standard") || !strcmp(collation, "search"))
+                    continue;
+
+                // Map keyword values to BCP 47 equivalents.
+                if (!strcmp(collation, "dictionary"))
+                    collation = "dict";
+                else if (!strcmp(collation, "gb2312han"))
+                    collation = "gb2312";
+                else if (!strcmp(collation, "phonebook"))
+                    collation = "phonebk";
+                else if (!strcmp(collation, "traditional"))
+                    collation = "trad";
+
+                keyLocaleData.push_back(std::string(collation));
+            }
+            uenum_close(enumeration);
+        }
+        break;
+    }
+    case indexOfExtensionKeyKn:
+        keyLocaleData.push_back(std::string("false"));
+        keyLocaleData.push_back(std::string("true"));
+        break;
+    case indexOfExtensionKeyKf:
+        keyLocaleData.push_back(std::string("false"));
+        keyLocaleData.push_back(std::string("lower"));
+        keyLocaleData.push_back(std::string("upper"));
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return keyLocaleData;
+}
+
+static std::vector<std::string> searchLocaleData(String* locale, size_t keyIndex)
+{
+    // 9.1 Internal slots of Service Constructors & 10.2.3 Internal slots (ECMA-402 2.0)
+    std::vector<std::string> keyLocaleData;
+    switch (keyIndex) {
+    case indexOfExtensionKeyCo:
+        // 10.2.3 "The first element of [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co must be null for all locale values."
+        keyLocaleData.push_back(std::string());
+        break;
+    case indexOfExtensionKeyKn:
+        keyLocaleData.push_back(std::string("false"));
+        keyLocaleData.push_back(std::string("true"));
+        break;
+    case indexOfExtensionKeyKf:
+        keyLocaleData.push_back(std::string("false"));
+        keyLocaleData.push_back(std::string("lower"));
+        keyLocaleData.push_back(std::string("upper"));
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return keyLocaleData;
+}
+
+Object* IntlCollator::create(ExecutionState& state, Context* realm, Value locales, Value options)
+{
+    Object* collator = new Object(state, realm->globalObject()->objectPrototype());
+    initialize(state, collator, realm, locales, options);
+    return collator;
+}
+
+IntlCollator::CollatorResolvedOptions IntlCollator::resolvedOptions(ExecutionState& state, Object* internalSlot)
+{
+    CollatorResolvedOptions opt;
+    opt.locale = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale())).value(state, internalSlot).toString(state);
+    opt.sensitivity = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity())).value(state, internalSlot).toString(state);
+    opt.usage = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage())).value(state, internalSlot).toString(state);
+    opt.collation = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().collation)).value(state, internalSlot).toString(state);
+    opt.numeric = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().numeric)).value(state, internalSlot).toBoolean(state);
+    opt.ignorePunctuation = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation())).value(state, internalSlot).toBoolean(state);
+    opt.caseFirst = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().caseFirst)).value(state, internalSlot).toString(state);
+    return opt;
+}
+
+void IntlCollator::initialize(ExecutionState& state, Object* collator, Context* realm, Value locales, Value options)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-10.1.1.1
+
+    collator->setPrototype(state, realm->globalObject()->intlCollator()->getFunctionPrototype(state));
+    // If collator has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
+    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
+    if (collator->hasInternalSlot() && collator->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
+    }
+
+    // Set the [[initializedIntlObject]] internal property of collator to true.
+    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
+
+    // Let requestedLocales be the result of calling the
+    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+
+    // If options is undefined, then
+    // Let options be the result of creating a new object as
+    // if by the expression new Object() where Object is the standard built-in constructor with that name.
+    if (options.isUndefined()) {
+        options = new Object(state, Object::PrototypeIsNull);
+    } else {
+        // Let options be ToObject(options).
+        options = options.toObject(state);
+    }
+    // Let u be the result of calling the GetOption abstract operation (defined in 9.2.9) with arguments options,
+    // "usage", "string", a List containing the two String values "sort" and "search", and "sort".
+    Value usageValues[2] = { state.context()->staticStrings().sort.string(), state.context()->staticStrings().search.string() };
+    Value u = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUsage().string(), Intl::StringValue, usageValues, 2, usageValues[0]);
+
+    // Set the [[usage]] internal property of collator to u.
+    collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage()), u, collator->internalSlot());
+
+    // Let Collator be the standard built-in object that is the initial value of Intl.Collator.
+    FunctionObject* Collator = realm->globalObject()->intlCollator();
+    UNUSED_VARIABLE(Collator);
+
+    // If u is "sort", then let localeData be the value of the [[sortLocaleData]] internal property of Collator;
+    Intl::LocaleDataImplFunction localeData;
+    if (u.equalsTo(state, state.context()->staticStrings().sort.string())) {
+        localeData = sortLocaleData;
+    } else {
+        // else let localeData be the value of the [[searchLocaleData]] internal property of Collator.
+        localeData = searchLocaleData;
+    }
+
+    // Let opt be a new Record.
+    StringMap opt;
+
+    // Let matcher be the result of calling the GetOption abstract operation with arguments
+    // options, "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit"
+    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
+    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
+    // Set opt.[[localeMatcher]] to matcher.
+    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
+
+    // Table 1 – Collator options settable through both extension keys and options properties
+    // Key Property    Type            Values
+    // kn  numeric    "boolean"
+    // kf  caseFirst  "string"   "upper", "lower", "false"
+    std::function<void(String * keyColumn, Value propertyColumn, Intl::OptionValueType type, Value * values, size_t valuesSize)> doTable1 = [&](String* keyColumn, Value propertyColumn, Intl::OptionValueType type, Value* values, size_t valuesSize) {
+        // Let key be the name given in the Key column of the row.
+        Value key = keyColumn;
+
+        // Let value be the result of calling the GetOption abstract operation, passing as arguments options, the name given in the Property column of the row,
+        // the string given in the Type column of the row,
+        // a List containing the Strings given in the Values column of the row or undefined if no strings are given, and undefined.
+
+        Value value = Intl::getOption(state, options.asObject(), propertyColumn, type, values, valuesSize, Value());
+        // If the string given in the Type column of the row is "boolean" and value is not undefined, then
+        // Let value be ToString(value).
+        if (type == Intl::BooleanValue && !value.isUndefined()) {
+            value = value.toString(state);
+        }
+        // Set opt.[[<key>]] to value.
+        opt.insert(std::make_pair(keyColumn->toNonGCUTF8StringData(), value.toString(state)));
+    };
+
+    doTable1(state.context()->staticStrings().lazyKn().string(), state.context()->staticStrings().numeric.string(), Intl::BooleanValue, nullptr, 0);
+    Value caseFirstValue[3] = { state.context()->staticStrings().lazyUpper().string(), state.context()->staticStrings().lazyLower().string(), state.context()->staticStrings().stringFalse.string() };
+    doTable1(state.context()->staticStrings().lazyKf().string(), state.context()->staticStrings().caseFirst.string(), Intl::StringValue, caseFirstValue, 3);
+
+    // Let relevantExtensionKeys be the value of the [[relevantExtensionKeys]] internal property of Collator.
+    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the [[availableLocales]]
+    // internal property of Collator, requestedLocales, opt, relevantExtensionKeys, and localeData.
+    StringMap r = Intl::resolveLocale(state, realm->vmInstance()->intlCollatorAvailableLocales(), requestedLocales, opt, intlCollatorRelevantExtensionKeys, intlCollatorRelevantExtensionKeysLength, localeData);
+
+    // Set the [[locale]] internal property of collator to the value of r.[[locale]].
+    collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), collator->internalSlot());
+
+    // Let i be 0.
+    size_t i = 0;
+    // Let len be the result of calling the [[Get]] internal method of relevantExtensionKeys with argument "length".
+    size_t len = intlCollatorRelevantExtensionKeysLength;
+    // Repeat while i < len:
+    while (i < len) {
+        // Let key be the result of calling the [[Get]] internal method of relevantExtensionKeys with argument ToString(i).
+        const char* key = intlCollatorRelevantExtensionKeys[i];
+        // If key is "co", then
+        AtomicString property;
+        Value value;
+        if (strcmp(key, "co") == 0) {
+            // Let property be "collation".
+            property = state.context()->staticStrings().collation;
+            // Let value be the value of r.[[co]].
+            auto iter = r.find("co");
+            // If value is null, then let value be "default".
+            if (r.end() == iter || iter->second->equals("")) {
+                value = state.context()->staticStrings().stringDefault.string();
+            } else {
+                value = iter->second;
+            }
+        } else if (strcmp(key, "kn") == 0) {
+            // Table 1 – Collator options settable through both extension keys and options properties
+            // Key Property    Type            Values
+            // kn  numeric    "boolean"
+            // kf  caseFirst  "string"   "upper", "lower", "false"
+
+            // Else use the row of Table 1 that contains the value of key in the Key column:
+            // Let property be the name given in the Property column of the row.
+            property = state.context()->staticStrings().numeric;
+            // Let value be the value of r.[[<key>]].
+            value = r.at("kn");
+            // If the name given in the Type column of the row is "boolean",
+            // then let value be the result of comparing value with "true".
+            value = Value(value.equalsTo(state, state.context()->staticStrings().stringTrue.string()));
+
+        } else if (strcmp(key, "kf") == 0) {
+            // Table 1 – Collator options settable through both extension keys and options properties
+            // Key Property    Type            Values
+            // kn  numeric    "boolean"
+            // kf  caseFirst  "string"   "upper", "lower", "false"
+
+            // Else use the row of Table 1 that contains the value of key in the Key column:
+            // Let property be the name given in the Property column of the row.
+            property = state.context()->staticStrings().caseFirst;
+            // Let value be the value of r.[[<key>]].
+            value = r.at("kf");
+            // If the name given in the Type column of the row is "boolean",
+            // then let value be the result of comparing value with "true".
+        } else {
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        // Set the [[<property>]] internal property of collator to value.
+        collator->internalSlot()->set(state, ObjectPropertyName(property), value, collator->internalSlot());
+        // Increase i by 1.
+        i++;
+    }
+    // Let s be the result of calling the GetOption abstract operation with arguments
+    // options, "sensitivity", "string", a List containing the four String values "base", "accent", "case", and "variant", and undefined.
+    Value sensitivityValue[4] = { state.context()->staticStrings().lazyBase().string(), state.context()->staticStrings().lazyAccent().string(), state.context()->staticStrings().lazyCase().string(), state.context()->staticStrings().lazyVariant().string() };
+    Value s = Intl::getOption(state, options.asObject(), Value(state.context()->staticStrings().lazySensitivity().string()), Intl::StringValue, sensitivityValue, 4, Value());
+    String* sensitivityString = s.toString(state);
+    // If s is undefined, then
+    // If u is "sort", then let s be "variant".
+    // Else
+    // Let dataLocale be the value of r.[[dataLocale]].
+    // Let dataLocaleData be the result of calling the [[Get]] internal operation of localeData with argument dataLocale.
+    // Let s be the result of calling the [[Get]] internal operation of dataLocaleData with argument "sensitivity".
+    if (sensitivityString->equals("base")) {
+        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyBase().string(), collator->internalSlot());
+    } else if (sensitivityString->equals("accent")) {
+        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyAccent().string(), collator->internalSlot());
+    } else if (sensitivityString->equals("case")) {
+        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyCase().string(), collator->internalSlot());
+    } else {
+        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyVariant().string(), collator->internalSlot());
+    }
+
+    // Let ip be the result of calling the GetOption abstract operation with arguments options, "ignorePunctuation", "boolean", undefined, and false.
+    Value ip = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyIgnorePunctuation().string(), Intl::BooleanValue, nullptr, 0, Value(false));
+    // Set the [[ignorePunctuation]] internal property of collator to ip.
+    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation()), ObjectPropertyDescriptor(ip));
+    // Set the [[boundCompare]] internal property of collator to undefined.
+    // Set the [[initializedCollator]] internal property of collator to true.
+    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()), ObjectPropertyDescriptor(Value(true)));
+    // Return collator.
+
+    {
+        Object* internalSlot = collator->internalSlot();
+        CollatorResolvedOptions opt = resolvedOptions(state, internalSlot);
+        UErrorCode status = U_ZERO_ERROR;
+        String* locale = opt.locale;
+        UColAttributeValue strength = UCOL_DEFAULT;
+        UColAttributeValue caseLevel = UCOL_OFF;
+        UColAttributeValue alternate = UCOL_DEFAULT;
+        UColAttributeValue numeric = UCOL_OFF;
+        UColAttributeValue normalization = UCOL_ON; // normalization is always on. ecma-402 needs this
+        UColAttributeValue caseFirst = UCOL_DEFAULT;
+
+        if (opt.usage->equals("search")) {
+            // If usage is search, we should append "-co-search" extension
+            size_t u = locale->find("-u-");
+            if (u == SIZE_MAX) {
+                StringBuilder sb;
+                sb.appendString(locale);
+                sb.appendString("-u-co-search");
+                locale = sb.finalize();
+            } else {
+                StringBuilder sb;
+                sb.appendString(locale);
+                sb.appendString("-co-search");
+                locale = sb.finalize();
+            }
+        } else {
+            ASSERT(opt.usage->equals("sort"));
+        }
+
+
+        String* sensitivity = opt.sensitivity;
+
+        if (sensitivity->equals("base")) {
+            strength = UCOL_PRIMARY;
+        } else if (sensitivity->equals("accent")) {
+            strength = UCOL_SECONDARY;
+        } else if (sensitivity->equals("case")) {
+            strength = UCOL_PRIMARY;
+            caseLevel = UCOL_ON;
+        } else {
+            ASSERT(sensitivity->equals("variant"));
+            strength = UCOL_TERTIARY;
+        }
+
+        if (opt.ignorePunctuation) {
+            alternate = UCOL_SHIFTED;
+        }
+
+        if (opt.numeric) {
+            numeric = UCOL_ON;
+        }
+
+        String* caseFirstString = opt.caseFirst;
+        if (caseFirstString->equals("upper")) {
+            caseFirst = UCOL_UPPER_FIRST;
+        } else if (caseFirstString->equals("lower")) {
+            caseFirst = UCOL_LOWER_FIRST;
+        } else {
+            ASSERT(caseFirstString->equals("false"));
+            caseFirst = UCOL_OFF;
+        }
+
+        UCollator* ucollator = ucol_open(locale->toUTF8StringData().data(), &status);
+        if (U_FAILURE(status)) {
+            return;
+        }
+
+        ucol_setAttribute(ucollator, UCOL_STRENGTH, strength, &status);
+        ucol_setAttribute(ucollator, UCOL_CASE_LEVEL, caseLevel, &status);
+        ucol_setAttribute(ucollator, UCOL_ALTERNATE_HANDLING, alternate, &status);
+        ucol_setAttribute(ucollator, UCOL_NUMERIC_COLLATION, numeric, &status);
+        ucol_setAttribute(ucollator, UCOL_NORMALIZATION_MODE, normalization, &status);
+        ucol_setAttribute(ucollator, UCOL_CASE_FIRST, caseFirst, &status);
+
+        if (U_FAILURE(status)) {
+            ucol_close(ucollator);
+            return;
+        }
+
+        internalSlot->setExtraData(ucollator);
+
+        internalSlot->addFinalizer([](Object* obj, void* data) {
+            Object* self = (Object*)obj;
+            ucol_close((UCollator*)self->extraData());
+        },
+                                   nullptr);
+    }
+}
+
+int IntlCollator::compare(ExecutionState& state, Object* collator, String* a, String* b)
+{
+    if (a->equals(b)) {
+        return 0;
+    }
+
+    auto utf16A = a->toUTF16StringData();
+    auto utf16B = b->toUTF16StringData();
+
+    UCollator* ucol = (UCollator*)collator->internalSlot()->extraData();
+    UCollationResult result = ucol_strcoll(ucol, utf16A.data(), utf16A.length(), utf16B.data(), utf16B.length());
+
+    switch (result) {
+    case UCOL_LESS:
+        return -1;
+    case UCOL_EQUAL:
+        return 0;
+    case UCOL_GREATER:
+        return 1;
+    default:
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to compare string a and b");
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlCollator.h
new file mode 100644 (file)
index 0000000..32b474c
--- /dev/null
@@ -0,0 +1,49 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlCollator__
+#define __EscargotIntlCollator__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlCollator {
+public:
+    struct CollatorResolvedOptions {
+        String* locale;
+        String* sensitivity;
+        String* usage;
+        String* collation;
+        bool numeric;
+        bool ignorePunctuation;
+        String* caseFirst;
+    };
+
+    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
+    static CollatorResolvedOptions resolvedOptions(ExecutionState& state, Object* internalSlot);
+    static void initialize(ExecutionState& state, Object* collator, Context* realm, Value locales, Value options);
+    static int compare(ExecutionState& state, Object* collator, String* a, String* b);
+};
+
+} // namespace Escargot
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.cpp
new file mode 100644 (file)
index 0000000..3c0926a
--- /dev/null
@@ -0,0 +1,1021 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
+ * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/VMInstance.h"
+#include "runtime/Value.h"
+#include "runtime/DateObject.h"
+#include "runtime/ArrayObject.h"
+#include "Intl.h"
+#include "IntlDateTimeFormat.h"
+
+namespace Escargot {
+
+static const char* const intlDateTimeFormatRelevantExtensionKeys[3] = { "ca", "nu", "hc" };
+static size_t intlDateTimeFormatRelevantExtensionKeysLength = 3;
+static const size_t indexOfExtensionKeyCa = 0;
+static const size_t indexOfExtensionKeyNu = 1;
+static const size_t indexOfExtensionKeyHc = 2;
+static const double minECMAScriptTime = -8.64E15;
+
+std::vector<std::string> Intl::calendarsForLocale(String* locale)
+{
+    std::vector<std::string> keyLocaleData;
+    UErrorCode status = U_ZERO_ERROR;
+    UEnumeration* calendars = ucal_getKeywordValuesForLocale("calendar", locale->toUTF8StringData().data(), false, &status);
+    ASSERT(U_SUCCESS(status));
+
+    status = U_ZERO_ERROR;
+    int32_t nameLength;
+    while (const char* availableName = uenum_next(calendars, &nameLength, &status)) {
+        ASSERT(U_SUCCESS(status));
+        status = U_ZERO_ERROR;
+        std::string calendar = std::string(availableName, nameLength);
+        // Ensure aliases used in language tag are allowed.
+        if (calendar == std::string("gregorian")) {
+            keyLocaleData.push_back(std::string("gregory"));
+        } else if (calendar == std::string("islamic-civil")) {
+            keyLocaleData.push_back(std::string("islamicc"));
+        } else if (calendar == std::string("ethiopic-amete-alem")) {
+            keyLocaleData.push_back(std::string("ethioaa"));
+        } else {
+            keyLocaleData.push_back(calendar);
+        }
+    }
+    uenum_close(calendars);
+
+    return keyLocaleData;
+}
+
+static std::vector<std::string> localeDataDateTimeFormat(String* locale, size_t keyIndex)
+{
+    std::vector<std::string> keyLocaleData;
+    switch (keyIndex) {
+    case indexOfExtensionKeyCa:
+        keyLocaleData = Intl::calendarsForLocale(locale);
+        break;
+    case indexOfExtensionKeyNu:
+        keyLocaleData = Intl::numberingSystemsForLocale(locale);
+        break;
+    case indexOfExtensionKeyHc:
+        keyLocaleData.push_back("h12");
+        keyLocaleData.push_back("h23");
+        keyLocaleData.push_back("h24");
+        keyLocaleData.push_back("h11");
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return keyLocaleData;
+}
+
+static bool equalIgnoringASCIICase(String* timeZoneName, const UTF16StringDataNonGCStd& ianaTimeZoneView)
+{
+    if (timeZoneName->length() != ianaTimeZoneView.size()) {
+        return false;
+    }
+    for (size_t i = 0; i < ianaTimeZoneView.size(); i++) {
+        if (tolower(ianaTimeZoneView[i]) != tolower(timeZoneName->charAt(i))) {
+            return false;
+        }
+    }
+    return true;
+}
+
+static String* canonicalizeTimeZoneName(ExecutionState& state, String* timeZoneName)
+{
+    // 6.4.1 IsValidTimeZoneName (timeZone)
+    // The abstract operation returns true if timeZone, converted to upper case as described in 6.1, is equal to one of the Zone or Link names of the IANA Time Zone Database, converted to upper case as described in 6.1. It returns false otherwise.
+    UErrorCode status = U_ZERO_ERROR;
+    UEnumeration* timeZones = ucal_openTimeZones(&status);
+    ASSERT(U_SUCCESS(status));
+
+    String* canonical = String::emptyString;
+    do {
+        status = U_ZERO_ERROR;
+        int32_t ianaTimeZoneLength;
+        // Time zone names are respresented as UChar[] in all related ICU apis.
+        const UChar* ianaTimeZone = uenum_unext(timeZones, &ianaTimeZoneLength, &status);
+        ASSERT(U_SUCCESS(status));
+
+        // End of enumeration.
+        if (!ianaTimeZone)
+            break;
+
+        UTF16StringDataNonGCStd ianaTimeZoneView((char16_t*)ianaTimeZone, ianaTimeZoneLength);
+        if (!equalIgnoringASCIICase(timeZoneName, ianaTimeZoneView))
+            continue;
+
+        // Found a match, now canonicalize.
+        // 6.4.2 CanonicalizeTimeZoneName (timeZone) (ECMA-402 2.0)
+        // 1. Let ianaTimeZone be the Zone or Link name of the IANA Time Zone Database such that timeZone, converted to upper case as described in 6.1, is equal to ianaTimeZone, converted to upper case as described in 6.1.
+        // 2. If ianaTimeZone is a Link name, then let ianaTimeZone be the corresponding Zone name as specified in the “backward” file of the IANA Time Zone Database.
+
+        UTF16StringDataNonGCStd buffer;
+        buffer.resize(ianaTimeZoneLength);
+        UBool isSystemID = false;
+        status = U_ZERO_ERROR;
+        auto canonicalLength = ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, (UChar*)buffer.data(), ianaTimeZoneLength, &isSystemID, &status);
+        if (status == U_BUFFER_OVERFLOW_ERROR) {
+            buffer.resize(canonicalLength);
+            isSystemID = false;
+            status = U_ZERO_ERROR;
+            ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, (UChar*)buffer.data(), canonicalLength, &isSystemID, &status);
+        }
+        ASSERT(U_SUCCESS(status));
+        canonical = new UTF16String(buffer.data(), canonicalLength);
+    } while (canonical->length() == 0);
+    uenum_close(timeZones);
+
+    // 3. If ianaTimeZone is "Etc/UTC" or "Etc/GMT", then return "UTC".
+    if (canonical->equals("Etc/UTC") || canonical->equals("Etc/GMT")) {
+        canonical = state.context()->staticStrings().UTC.string();
+    }
+
+    // 4. Return ianaTimeZone.
+    return canonical;
+}
+
+
+static void toDateTimeOptionsTest(ExecutionState& state, Value options, AtomicString name, bool& needDefaults)
+{
+    Value r = options.asObject()->get(state, name).value(state, options.asObject());
+    if (!r.isUndefined()) {
+        needDefaults = false;
+    }
+}
+
+static String* defaultTimeZone(ExecutionState& state)
+{
+    // ensure timezone
+    state.context()->vmInstance()->timezone();
+    return String::fromUTF8(state.context()->vmInstance()->timezoneID().data(), state.context()->vmInstance()->timezoneID().length());
+}
+
+Object* IntlDateTimeFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
+{
+    Object* dateTimeFormat = new Object(state, realm->globalObject()->intlDateTimeFormatPrototype());
+    initialize(state, dateTimeFormat, locales, options);
+    return dateTimeFormat;
+}
+
+static std::string readHourCycleFromPattern(const UTF16StringDataNonGCStd& patternString)
+{
+    bool inQuote = false;
+    for (size_t i = 0; i < patternString.length(); i++) {
+        auto ch = patternString[i];
+        switch (ch) {
+        case '\'':
+            inQuote = !inQuote;
+            break;
+        case 'K':
+            if (!inQuote) {
+                return "h11";
+            }
+            break;
+        case 'h':
+            if (!inQuote) {
+                return "h12";
+            }
+            break;
+        case 'H':
+            if (!inQuote) {
+                return "h23";
+            }
+            break;
+        case 'k':
+            if (!inQuote) {
+                return "h24";
+            }
+            break;
+        }
+    }
+    return "";
+}
+
+UTF16StringDataNonGCStd updateHourCycleInPatternDueToHourCycle(const UTF16StringDataNonGCStd& pattern, String* hc)
+{
+    char16_t newHcChar;
+    if (hc->equals("h11")) {
+        newHcChar = 'K';
+    } else if (hc->equals("h12")) {
+        newHcChar = 'h';
+    } else if (hc->equals("h23")) {
+        newHcChar = 'H';
+    } else {
+        ASSERT(hc->equals("h24"));
+        newHcChar = 'k';
+    }
+    bool inQuote = false;
+    UTF16StringDataNonGCStd result;
+    for (size_t i = 0; i < pattern.length(); i++) {
+        auto ch = pattern[i];
+        switch (ch) {
+        case '\'':
+            inQuote = !inQuote;
+            result += ch;
+            break;
+        case 'K':
+        case 'k':
+        case 'H':
+        case 'h':
+            result += inQuote ? ch : newHcChar;
+            break;
+        default:
+            result += ch;
+            break;
+        }
+    }
+
+    return result;
+}
+
+
+void IntlDateTimeFormat::initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options)
+{
+    // If dateTimeFormat has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
+    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
+    if (dateTimeFormat->hasInternalSlot() && dateTimeFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
+    }
+
+    // Set the [[initializedIntlObject]] internal property of dateTimeFormat to true.
+    dateTimeFormat->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
+
+    // Let requestedLocales be the result of calling the
+    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+
+    // Let options be the result of calling the ToDateTimeOptions abstract operation (defined below) with arguments options, "any", and "date".
+    options = toDateTimeOptions(state, options, state.context()->staticStrings().lazyAny().string(), state.context()->staticStrings().lazyDate().string());
+
+    // Let opt be a new Record.
+    StringMap opt;
+    // Let matcher be the result of calling the GetOption abstract operation (defined in 9.2.9) with arguments options,
+    // "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit".
+    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
+    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
+
+    // Set opt.[[localeMatcher]] to matcher.
+    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
+
+    // Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined).
+    Value calendar = Intl::getOption(state, options.asObject(), state.context()->staticStrings().calendar.string(), Intl::StringValue, nullptr, 0, Value());
+    // If calendar is not undefined, then
+    if (!calendar.isUndefined()) {
+        // If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
+        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(calendar.asString())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The calendar value you gave is not valid");
+        }
+    }
+    // Set opt.[[ca]] to calendar.
+    if (!calendar.isUndefined()) {
+        opt.insert(std::make_pair("ca", calendar.toString(state)));
+    }
+    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
+    Value numberingSystem = Intl::getOption(state, options.asObject(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
+    // If numberingSystem is not undefined, then
+    if (!numberingSystem.isUndefined()) {
+        // If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
+        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
+        }
+    }
+    // Set opt.[[nu]] to numberingSystem.
+    if (!numberingSystem.isUndefined()) {
+        opt.insert(std::make_pair("nu", numberingSystem.toString(state)));
+    }
+
+    // Let hour12 be ? GetOption(options, "hour12", "boolean", undefined, undefined).
+    Value hour12 = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyHour12().string(), Intl::BooleanValue, nullptr, 0, Value());
+
+    // Let hourCycle be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
+    Value hourCycleValue[4] = { state.context()->staticStrings().lazyH11().string(), state.context()->staticStrings().lazyH12().string(), state.context()->staticStrings().lazyH23().string(), state.context()->staticStrings().lazyH24().string() };
+    Value hourCycle = Intl::getOption(state, options.asObject(), state.context()->staticStrings().hourCycle.string(), Intl::StringValue, hourCycleValue, 4, Value());
+    // If hour12 is not undefined, then
+    if (!hour12.isUndefined()) {
+        // Let hourCycle be null.
+        hourCycle = Value(Value::Null);
+    }
+    // Set opt.[[hc]] to hourCycle.
+    if (!hourCycle.isUndefinedOrNull()) {
+        opt.insert(std::make_pair("hc", hourCycle.toString(state)));
+    }
+
+    // Let DateTimeFormat be the standard built-in object that is the initial value of Intl.DateTimeFormat.
+    // Let localeData be the value of the [[localeData]] internal property of DateTimeFormat.
+    const auto& availableLocales = state.context()->vmInstance()->intlDateTimeFormatAvailableLocales();
+
+    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the
+    // [[availableLocales]] internal property of DateTimeFormat, requestedLocales, opt, the [[relevantExtensionKeys]] internal property of DateTimeFormat, and localeData.
+    StringMap r = Intl::resolveLocale(state, availableLocales, requestedLocales, opt, intlDateTimeFormatRelevantExtensionKeys, intlDateTimeFormatRelevantExtensionKeysLength, localeDataDateTimeFormat);
+
+    // The resolved locale doesn't include a hc Unicode extension value if the hour12 or hourCycle option is also present.
+    if (!hour12.isUndefined() || !hourCycle.isUndefinedOrNull()) {
+        auto iter = r.find("locale");
+        String* locale = iter->second;
+        iter->second = Intl::canonicalizeLanguageTag(locale->toNonGCUTF8StringData(), "hc").canonicalizedTag.value();
+    }
+
+    // Set the [[locale]] internal property of dateTimeFormat to the value of r.[[locale]].
+    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), dateTimeFormat->internalSlot());
+    // Set the [[calendar]] internal property of dateTimeFormat to the value of r.[[ca]].
+    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().calendar), r.at("ca"), dateTimeFormat->internalSlot());
+    // Set dateTimeFormat.[[hourCycle]] to r.[[hc]].
+    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), r.at("hc"), dateTimeFormat->internalSlot());
+    // Set the [[numberingSystem]] internal property of dateTimeFormat to the value of r.[[nu]].
+    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), r.at("nu"), dateTimeFormat->internalSlot());
+
+    // Let dataLocale be the value of r.[[dataLocale]].
+    Value dataLocale = r.at("dataLocale");
+
+    // Always use ICU date format generator, rather than our own pattern list and matcher.
+    UErrorCode status = U_ZERO_ERROR;
+    LocalResourcePointer<UDateTimePatternGenerator> generator(udatpg_open(dataLocale.toString(state)->toUTF8StringData().data(), &status),
+                                                              [](UDateTimePatternGenerator* d) { udatpg_close(d); });
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+        return;
+    }
+
+    // Let tz be the result of calling the [[Get]] internal method of options with argument "timeZone".
+    Value tz = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, options.asObject());
+
+    // If tz is not undefined, then
+    if (!tz.isUndefined()) {
+        // Let tz be ToString(tz).
+        String* tzString = tz.toString(state);
+        // Convert tz to upper case as described in 6.1.
+        // NOTE:   If an implementation accepts additional time zone values, as permitted under certain conditions by the Conformance clause,
+        // different casing rules apply., If tz is not "UTC", then throw a RangeError exception.
+        tz = canonicalizeTimeZoneName(state, tzString);
+        tzString = tz.toString(state);
+        if (tzString->length() == 0) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid timezone value");
+        }
+    } else {
+        tz = defaultTimeZone(state);
+    }
+    // Set the [[timeZone]] internal property of dateTimeFormat to tz.
+    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone()), tz, dateTimeFormat->internalSlot());
+
+    // Let opt be a new Record.
+    opt.clear();
+
+    // Table 3 – Components of date and time formats
+    // Property    Values
+    // weekday "narrow", "short", "long"
+    // era "narrow", "short", "long"
+    // year    "2-digit", "numeric"
+    // month   "2-digit", "numeric", "narrow", "short", "long"
+    // day "2-digit", "numeric"
+    // hour    "2-digit", "numeric"
+    // minute  "2-digit", "numeric"
+    // second  "2-digit", "numeric"
+    // timeZoneName    "short", "long"
+
+    // For each row of Table 3, except the header row, do:
+    std::function<void(String * prop, Value * values, size_t valuesSize)> doTable3 = [&](String* prop, Value* values, size_t valuesSize) {
+        // Let prop be the name given in the Property column of the row.
+        // Let value be the result of calling the GetOption abstract operation, passing as argument options, the name given in the Property column of the row,
+        // "string", a List containing the strings given in the Values column of the row, and undefined.
+        Value value = Intl::getOption(state, options.asObject(), prop, Intl::StringValue, values, valuesSize, Value());
+        // Set opt.[[<prop>]] to value.
+        if (!value.isUndefined()) {
+            opt.insert(std::make_pair(prop->toNonGCUTF8StringData(), value.toString(state)));
+        }
+    };
+
+    StringBuilder skeletonBuilder;
+
+    Value narrowShortLongValues[3] = { state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
+
+    doTable3(state.context()->staticStrings().lazyWeekday().string(), narrowShortLongValues, 3);
+
+    String* ret = opt.at("weekday");
+
+    if (ret->equals("narrow")) {
+        skeletonBuilder.appendString("EEEEE");
+    } else if (ret->equals("short")) {
+        skeletonBuilder.appendString("EEE");
+    } else if (ret->equals("long")) {
+        skeletonBuilder.appendString("EEEE");
+    }
+
+    doTable3(state.context()->staticStrings().lazyEra().string(), narrowShortLongValues, 3);
+
+    ret = opt.at("era");
+    if (ret->equals("narrow")) {
+        skeletonBuilder.appendString("GGGGG");
+    } else if (ret->equals("short")) {
+        skeletonBuilder.appendString("GGG");
+    } else if (ret->equals("long")) {
+        skeletonBuilder.appendString("GGGG");
+    }
+
+    Value twoDightNumericValues[2] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string() };
+    doTable3(state.context()->staticStrings().lazyYear().string(), twoDightNumericValues, 2);
+
+    ret = opt.at("year");
+    if (ret->equals("2-digit")) {
+        skeletonBuilder.appendString("yy");
+    } else if (ret->equals("numeric")) {
+        skeletonBuilder.appendString("y");
+    }
+
+    Value allValues[5] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string(), state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
+    doTable3(state.context()->staticStrings().lazyMonth().string(), allValues, 5);
+
+    ret = opt.at("month");
+    if (ret->equals("2-digit")) {
+        skeletonBuilder.appendString("MM");
+    } else if (ret->equals("numeric")) {
+        skeletonBuilder.appendString("M");
+    } else if (ret->equals("narrow")) {
+        skeletonBuilder.appendString("MMMMM");
+    } else if (ret->equals("short")) {
+        skeletonBuilder.appendString("MMM");
+    } else if (ret->equals("long")) {
+        skeletonBuilder.appendString("MMMM");
+    }
+
+    doTable3(state.context()->staticStrings().lazyDay().string(), twoDightNumericValues, 2);
+
+    ret = opt.at("day");
+    if (ret->equals("2-digit")) {
+        skeletonBuilder.appendString("dd");
+    } else if (ret->equals("numeric")) {
+        skeletonBuilder.appendString("d");
+    }
+
+    doTable3(state.context()->staticStrings().lazyHour().string(), twoDightNumericValues, 2);
+
+    String* hour = ret = opt.at("hour");
+    Value hr12Value = hour12;
+    bool isHour12Undefined = hr12Value.isUndefined();
+    bool hr12 = hr12Value.toBoolean(state);
+
+    if (isHour12Undefined) {
+        if (ret->equals("2-digit"))
+            skeletonBuilder.appendString("jj");
+        else if (ret->equals("numeric"))
+            skeletonBuilder.appendChar('j');
+    } else if (hr12) {
+        if (ret->equals("2-digit"))
+            skeletonBuilder.appendString("hh");
+        else if (ret->equals("numeric"))
+            skeletonBuilder.appendChar('h');
+    } else {
+        if (ret->equals("2-digit"))
+            skeletonBuilder.appendString("HH");
+        else if (ret->equals("numeric"))
+            skeletonBuilder.appendChar('H');
+    }
+
+    doTable3(state.context()->staticStrings().lazyMinute().string(), twoDightNumericValues, 2);
+
+    ret = opt.at("minute");
+    if (ret->equals("2-digit")) {
+        skeletonBuilder.appendString("mm");
+    } else if (ret->equals("numeric")) {
+        skeletonBuilder.appendString("m");
+    }
+
+    doTable3(state.context()->staticStrings().lazySecond().string(), twoDightNumericValues, 2);
+
+    ret = opt.at("second");
+    if (ret->equals("2-digit")) {
+        skeletonBuilder.appendString("ss");
+    } else if (ret->equals("numeric")) {
+        skeletonBuilder.appendString("s");
+    }
+
+    Value shortLongValues[2] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
+    doTable3(state.context()->staticStrings().lazyTimeZoneName().string(), shortLongValues, 2);
+
+    ret = opt.at("timeZoneName");
+    if (ret->equals("short")) {
+        skeletonBuilder.appendString("z");
+    } else if (ret->equals("long")) {
+        skeletonBuilder.appendString("zzzz");
+    }
+
+    // Let dataLocaleData be the result of calling the [[Get]] internal method of localeData with argument dataLocale.
+    // Let formats be the result of calling the [[Get]] internal method of dataLocaleData with argument "formats".
+    // Let matcher be the result of calling the GetOption abstract operation with arguments options,
+    // "formatMatcher", "string", a List containing the two String values "basic" and "best fit", and "best fit".
+    Value formatMatcherValues[2] = { state.context()->staticStrings().lazyBasic().string(), state.context()->staticStrings().lazyBestFit().string() };
+    matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyFormatMatcher().string(), Intl::StringValue, formatMatcherValues, 2, formatMatcherValues[1]);
+
+    // Always use ICU date format generator, rather than our own pattern list and matcher.
+    // Covers steps 28-36.
+    String* skeleton = skeletonBuilder.finalize();
+    UTF16StringData skeletonUTF16String = skeleton->toUTF16StringData();
+
+    // If dateTimeFormat.[[Hour]] is not undefined, then
+    bool hasHourOption = hour->length();
+    if (hasHourOption) {
+        // Let hcDefault be dataLocaleData.[[hourCycle]].
+        UTF16StringDataNonGCStd patternBuffer;
+        patternBuffer.resize(32);
+        status = U_ZERO_ERROR;
+        auto patternLength = udatpg_getBestPattern(generator.get(), u"jjmm", 4, (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
+        patternBuffer.resize(patternLength);
+        if (status == U_BUFFER_OVERFLOW_ERROR) {
+            status = U_ZERO_ERROR;
+            patternBuffer.resize(patternLength);
+            udatpg_getBestPattern(generator.get(), u"jjmm", 4, (UChar*)patternBuffer.data(), patternLength, &status);
+        }
+        ASSERT(U_SUCCESS(status));
+        auto hcDefault = readHourCycleFromPattern(patternBuffer);
+        // Let hc be dateTimeFormat.[[HourCycle]].
+        auto hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot()).asString();
+        // If hc is null, then
+        if (!hc->length()) {
+            // Set hc to hcDefault.
+            hc = String::fromUTF8(hcDefault.data(), hcDefault.size());
+        }
+        // If hour12 is not undefined, then
+        if (!hour12.isUndefined()) {
+            // If hour12 is true, then
+            if (hour12.asBoolean()) {
+                // If hcDefault is "h11" or "h23", then
+                if (hcDefault == "h11" || hcDefault == "h23") {
+                    // Set hc to "h11".
+                    hc = state.context()->staticStrings().lazyH11().string();
+                } else {
+                    // Set hc to "h12".
+                    hc = state.context()->staticStrings().lazyH12().string();
+                }
+            } else {
+                // Assert: hour12 is false.
+                // If hcDefault is "h11" or "h23", then
+                if (hcDefault == "h11" || hcDefault == "h23") {
+                    // Set hc to "h23".
+                    hc = state.context()->staticStrings().lazyH23().string();
+                } else {
+                    // Else,
+                    // Set hc to "h24".
+                    hc = state.context()->staticStrings().lazyH24().string();
+                }
+            }
+        }
+
+        // Let dateTimeFormat.[[HourCycle]] to hc.
+        dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(hc), dateTimeFormat->internalSlot());
+    } else {
+        // Set dateTimeFormat.[[HourCycle]] to undefined.
+        dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(), dateTimeFormat->internalSlot());
+        // Let pattern be bestFormat.[[pattern]].
+    }
+
+    UTF16StringDataNonGCStd patternBuffer;
+    patternBuffer.resize(32);
+    status = U_ZERO_ERROR;
+    auto patternLength = udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+    patternBuffer.resize(patternLength);
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        patternBuffer.resize(patternLength);
+        udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternLength, &status);
+    }
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+        return;
+    }
+
+    Value hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot());
+    if (!hc.isUndefined() && hc.asString()->length()) {
+        patternBuffer = updateHourCycleInPatternDueToHourCycle(patternBuffer, hc.asString());
+    }
+
+    bool inQuote = false;
+    unsigned length = patternBuffer.length();
+    for (unsigned i = 0; i < length; ++i) {
+        char16_t currentCharacter = patternBuffer[i];
+
+        if (currentCharacter == '\'') {
+            inQuote = !inQuote;
+        }
+
+        if (!isASCIIAlpha(currentCharacter))
+            continue;
+
+        unsigned count = 1;
+        while (i + 1 < length && patternBuffer[i + 1] == currentCharacter) {
+            ++count;
+            ++i;
+        }
+
+        if (hasHourOption && !inQuote) {
+            if (currentCharacter == 'h' || currentCharacter == 'K') {
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(true), dateTimeFormat->internalSlot());
+            } else if (currentCharacter == 'H' || currentCharacter == 'k') {
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(false), dateTimeFormat->internalSlot());
+            }
+        }
+
+        switch (currentCharacter) {
+        case 'G':
+            if (count <= 3)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
+            else if (count == 4)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
+            else if (count == 5)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'y':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'M':
+        case 'L':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            else if (count == 3)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
+            else if (count == 4)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
+            else if (count == 5)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'E':
+        case 'e':
+        case 'c':
+            if (count <= 3)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
+            else if (count == 4)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
+            else if (count == 5)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'd':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'h':
+        case 'H':
+        case 'k':
+        case 'K':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'm':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            break;
+        case 's':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
+            else if (count == 2)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+            break;
+        case 'z':
+        case 'v':
+        case 'V':
+            if (count == 1)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
+            else if (count == 4)
+                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
+            break;
+        }
+    }
+
+    status = U_ZERO_ERROR;
+    UTF16StringData timeZoneView = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, dateTimeFormat->internalSlot()).toString(state)->toUTF16StringData();
+    UTF8StringData localeStringView = r.at("locale")->toUTF8StringData();
+    UDateFormat* icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, localeStringView.data(), (UChar*)timeZoneView.data(), timeZoneView.length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+        return;
+    }
+
+    dateTimeFormat->internalSlot()->setExtraData(icuDateFormat);
+
+    dateTimeFormat->internalSlot()->addFinalizer([](Object* obj, void* data) {
+        Object* self = (Object*)obj;
+        udat_close((UDateFormat*)self->extraData());
+    },
+                                                 nullptr);
+
+    // Set dateTimeFormat.[[boundFormat]] to undefined.
+    // Set dateTimeFormat.[[initializedDateTimeFormat]] to true.
+    dateTimeFormat->internalSlot()->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()), ObjectPropertyDescriptor(Value(true)));
+
+    status = U_ZERO_ERROR;
+    UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(icuDateFormat));
+    std::string type(ucal_getType(cal, &status));
+    if (status == U_ZERO_ERROR && std::string("gregorian") == type) {
+        ucal_setGregorianChange(cal, minECMAScriptTime, &status);
+    }
+    // Return dateTimeFormat.
+    return;
+}
+
+UTF16StringDataNonGCStd IntlDateTimeFormat::format(ExecutionState& state, Object* dateTimeFormat, double x)
+{
+    // If x is not a finite Number, then throw a RangeError exception.
+    // If x is NaN, throw a RangeError exception
+    // If abs(time) > 8.64 × 10^15, return NaN.
+    if (std::isinf(x) || std::isnan(x) || !IS_IN_TIME_RANGE(x)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "date value is valid in DateTimeFormat format()");
+    }
+
+    x = Value(x).toInteger(state);
+
+    UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
+
+    // Delegate remaining steps to ICU.
+    UErrorCode status = U_ZERO_ERROR;
+    UTF16StringDataNonGCStd result;
+    result.resize(32);
+    auto resultLength = udat_format(udat, x, (UChar*)result.data(), result.size(), nullptr, &status);
+    result.resize(resultLength);
+
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        udat_format(udat, x, (UChar*)result.data(), resultLength, nullptr, &status);
+    }
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format date value");
+    }
+
+    return result;
+}
+
+
+static String* icuFieldTypeToPartName(ExecutionState& state, int32_t fieldName)
+{
+    if (fieldName == -1) {
+        return state.context()->staticStrings().lazyLiteral().string();
+    }
+
+    switch ((UDateFormatField)fieldName) {
+    case UDAT_ERA_FIELD:
+        return state.context()->staticStrings().lazyEra().string();
+    case UDAT_YEAR_FIELD:
+    case UDAT_YEAR_WOY_FIELD:
+    case UDAT_EXTENDED_YEAR_FIELD:
+    case UDAT_YEAR_NAME_FIELD:
+        return state.context()->staticStrings().lazyYear().string();
+    case UDAT_MONTH_FIELD:
+    case UDAT_STANDALONE_MONTH_FIELD:
+        return state.context()->staticStrings().lazyMonth().string();
+    case UDAT_DATE_FIELD:
+    case UDAT_JULIAN_DAY_FIELD:
+        return state.context()->staticStrings().lazyDay().string();
+    case UDAT_HOUR_OF_DAY1_FIELD:
+    case UDAT_HOUR_OF_DAY0_FIELD:
+    case UDAT_HOUR1_FIELD:
+    case UDAT_HOUR0_FIELD:
+        return state.context()->staticStrings().lazyHour().string();
+    case UDAT_MINUTE_FIELD:
+        return state.context()->staticStrings().lazyMinute().string();
+    case UDAT_SECOND_FIELD:
+        return state.context()->staticStrings().lazySecond().string();
+    case UDAT_DAY_OF_WEEK_FIELD:
+    case UDAT_STANDALONE_DAY_FIELD:
+    case UDAT_DOW_LOCAL_FIELD:
+    case UDAT_DAY_OF_WEEK_IN_MONTH_FIELD:
+        return state.context()->staticStrings().lazyWeekday().string();
+    case UDAT_AM_PM_FIELD:
+        return state.context()->staticStrings().lazyDayPeriod().string();
+    case UDAT_TIMEZONE_FIELD:
+        return state.context()->staticStrings().lazyTimeZoneName().string();
+    default:
+        ASSERT_NOT_REACHED();
+        return String::emptyString;
+    }
+}
+
+
+ArrayObject* IntlDateTimeFormat::formatToParts(ExecutionState& state, Object* dateTimeFormat, double x)
+{
+    // If x is not a finite Number, then throw a RangeError exception.
+    // If x is NaN, throw a RangeError exception
+    // If abs(time) > 8.64 × 10^15, return NaN.
+    if (std::isinf(x) || std::isnan(x) || !IS_IN_TIME_RANGE(x)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "date value is not valid in DateTimeFormat formatToParts()");
+    }
+
+    x = Value(x).toInteger(state);
+
+    ArrayObject* result = new ArrayObject(state);
+
+    UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
+
+    UErrorCode status = U_ZERO_ERROR;
+
+    UFieldPositionIterator* fpositer;
+    fpositer = ufieldpositer_open(&status);
+    ASSERT(U_SUCCESS(status));
+
+    UTF16StringDataNonGCStd resultString;
+    resultString.resize(32);
+    auto resultLength = udat_formatForFields(udat, x, (UChar*)resultString.data(), resultString.size(), fpositer, &status);
+    resultString.resize(resultLength);
+
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        udat_formatForFields(udat, x, (UChar*)resultString.data(), resultLength, fpositer, &status);
+    }
+
+    struct FieldItem {
+        int32_t start;
+        int32_t end;
+        int32_t type;
+    };
+
+    std::vector<FieldItem> fields;
+    while (true) {
+        int32_t start;
+        int32_t end;
+        int32_t type = ufieldpositer_next(fpositer, &start, &end);
+        if (type < 0) {
+            break;
+        }
+
+        FieldItem item;
+        item.start = start;
+        item.end = end;
+        item.type = type;
+
+        fields.push_back(item);
+    }
+
+    ufieldpositer_close(fpositer);
+
+    // add literal field if needs
+    std::vector<FieldItem> literalFields;
+    for (size_t i = 0; i < resultString.length(); i++) {
+        bool found = false;
+        for (size_t j = 0; j < fields.size(); j++) {
+            if ((size_t)fields[j].start <= i && i < (size_t)fields[j].end) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            size_t end = i + 1;
+            while (end != resultString.length()) {
+                bool found = false;
+                for (size_t j = 0; j < fields.size(); j++) {
+                    if ((size_t)fields[j].start <= end && end < (size_t)fields[j].end) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (found) {
+                    break;
+                }
+                end++;
+            }
+
+            FieldItem newItem;
+            newItem.type = -1;
+            newItem.start = i;
+            newItem.end = end;
+            i = end - 1;
+            literalFields.push_back(newItem);
+        }
+    }
+    fields.insert(fields.end(), literalFields.begin(), literalFields.end());
+
+    std::sort(fields.begin(), fields.end(),
+              [](const FieldItem& a, const FieldItem& b) -> bool {
+                  return a.start < b.start;
+              });
+
+    AtomicString typeAtom(state, "type", 4);
+    AtomicString valueAtom = state.context()->staticStrings().value;
+
+    for (size_t i = 0; i < fields.size(); i++) {
+        const FieldItem& item = fields[i];
+
+        Object* o = new Object(state);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(icuFieldTypeToPartName(state, item.type), ObjectPropertyDescriptor::AllPresent));
+        auto sub = resultString.substr(item.start, item.end - item.start);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
+
+        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
+    }
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format date value");
+    }
+
+    return result;
+}
+
+Value IntlDateTimeFormat::toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults)
+{
+    // If options is undefined, then let options be null, else let options be ToObject(options).
+    if (options.isUndefined()) {
+        options = Value(Value::Null);
+    } else {
+        options = options.toObject(state);
+    }
+    // Let create be the standard built-in function object defined in ES5, 15.2.3.5.
+    // Let options be the result of calling the [[Call]] internal method of create with undefined as the this value
+    // and an argument list containing the single item options.
+    options = Object::call(state, state.context()->globalObject()->objectCreate(), Value(), 1, &options);
+
+    // Let needDefaults be true.
+    bool needDefaults = true;
+    // If required is "date" or "any", then
+    if (required.equalsTo(state, state.context()->staticStrings().lazyDate().string()) || required.equalsTo(state, state.context()->staticStrings().lazyAny().string())) {
+        // For each of the property names "weekday", "year", "month", "day":
+        // If the result of calling the [[Get]] internal method of options with the property name is not undefined, then let needDefaults be false.
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyWeekday(), needDefaults);
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyYear(), needDefaults);
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyMonth(), needDefaults);
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyDay(), needDefaults);
+    }
+    // If required is "time" or "any", then
+    if (required.equalsTo(state, state.context()->staticStrings().lazyTime().string()) || required.equalsTo(state, state.context()->staticStrings().lazyAny().string())) {
+        // For each of the property names "hour", "minute", "second":
+        // If the result of calling the [[Get]] internal method of options with the property name is not undefined, then let needDefaults be false.
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyHour(), needDefaults);
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyMinute(), needDefaults);
+        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazySecond(), needDefaults);
+    }
+
+    // If needDefaults is true and defaults is either "date" or "all", then
+    if (needDefaults && (defaults.equalsTo(state, state.context()->staticStrings().lazyDate().string()) || defaults.equalsTo(state, state.context()->staticStrings().all.string()))) {
+        // For each of the property names "year", "month", "day":
+        // Call the [[DefineOwnProperty]] internal method of options with the property name,
+        // Property Descriptor {[[Value]]: "numeric", [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+        String* v = state.context()->staticStrings().numeric.string();
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+    }
+    // If needDefaults is true and defaults is either "time" or "all", then
+    if (needDefaults && (defaults.equalsTo(state, state.context()->staticStrings().lazyTime().string()) || defaults.equalsTo(state, state.context()->staticStrings().all.string()))) {
+        // For each of the property names "hour", "minute", "second":
+        // Call the [[DefineOwnProperty]] internal method of options with the property name, Property Descriptor {[[Value]]: "numeric", [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
+        String* v = state.context()->staticStrings().numeric.string();
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
+    }
+
+    return options;
+}
+
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlDateTimeFormat.h
new file mode 100644 (file)
index 0000000..49eda7a
--- /dev/null
@@ -0,0 +1,40 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlDateTimeFormat__
+#define __EscargotIntlDateTimeFormat__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlDateTimeFormat {
+public:
+    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
+    static void initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options);
+    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* dateTimeFormat, double x);
+    static ArrayObject* formatToParts(ExecutionState& state, Object* dateTimeFormat, double x);
+    static Value toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults);
+};
+
+} // namespace Escargot
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.cpp
new file mode 100644 (file)
index 0000000..cf24b39
--- /dev/null
@@ -0,0 +1,372 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "Intl.h"
+#include "IntlLocale.h"
+
+namespace Escargot {
+
+static Intl::CanonicalizedLangunageTag applyOptionsToTag(ExecutionState& state, String* tag, Optional<Object*> options)
+{
+    // we should not allow grandfathered tag like `i-default`(invalid lang), `no-bok`(have extlang)
+    auto u8Tag = tag->toNonGCUTF8StringData();
+    auto tagPart = split(u8Tag, '-');
+    if ((tagPart.size() > 0 && tagPart[0].length() == 1) || (tagPart.size() > 1 && tagPart[1].length() == 3 && isAllSpecialCharacters(tagPart[1], isASCIIAlpha))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
+    }
+
+    // If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
+    auto parsedResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(u8Tag);
+    if (!parsedResult.canonicalizedTag) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
+    }
+
+    // We should not allow extlang here
+    if (parsedResult.extLang.size()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
+    }
+
+    String* languageString = state.context()->staticStrings().language.string();
+    // Let language be ? GetOption(options, "language", "string", undefined, undefined).
+    Value language = options ? Intl::getOption(state, options.value(), languageString, Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If language is not undefined, then
+    if (!language.isUndefined()) {
+        // If language does not match the unicode_language_subtag production, throw a RangeError exception.
+        auto u8Lang = language.asString()->toNonGCUTF8StringData();
+        UErrorCode status = U_ZERO_ERROR;
+        int32_t len = uloc_forLanguageTag(u8Lang.data(), nullptr, 0, nullptr, &status);
+        UNUSED_VARIABLE(len);
+        if (status != U_BUFFER_OVERFLOW_ERROR || u8Lang.length() != 2 || !isAllSpecialCharacters(u8Lang, isASCIIAlpha)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "lanuage tag you give into Intl.Locale is invalid");
+        }
+    }
+
+    String* scriptString = state.context()->staticStrings().script.string();
+    // Let script be ? GetOption(options, "script", "string", undefined, undefined).
+    Value script = options ? Intl::getOption(state, options.value(), scriptString, Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If script is not undefined, then
+    if (!script.isUndefined()) {
+        // If script does not match the unicode_script_subtag, throw a RangeError exception.
+        String* scriptString = script.asString();
+        if (scriptString->length() != 4 || !scriptString->isAllSpecialCharacters(isASCIIAlpha)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "script you give into Intl.Locale is invalid");
+        }
+    }
+
+    String* regionString = state.context()->staticStrings().region.string();
+    // Let region be ? GetOption(options, "region", "string", undefined, undefined).
+    Value region = options ? Intl::getOption(state, options.value(), regionString, Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If region is not undefined, then
+    if (!region.isUndefined()) {
+        // If region does not match the unicode_region_subtag, throw a RangeError exception.
+        String* regionString = region.asString();
+        if ((!(regionString->length() == 2 && regionString->isAllSpecialCharacters(isASCIIAlpha)) && !(regionString->length() == 3 && regionString->isAllSpecialCharacters(isASCIIDigit)))) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "region you give into Intl.Locale is invalid");
+        }
+    }
+
+    // Let tag to CanonicalizeUnicodeLocaleId(tag).
+    // If language is not undefined,
+    // Assert: tag matches the unicode_locale_id production.
+    // Set tag to tag with the substring corresponding to the unicode_language_subtag production of the unicode_language_id replaced by the string language.
+    // If script is not undefined, then
+    // If tag does not contain a unicode_script_subtag production of the unicode_language_id, then
+    // Set tag to the concatenation of the unicode_language_subtag production of the unicode_languge_id of tag, "-", script, and the rest of tag.
+    // Else,
+    // Set tag to tag with the substring corresponding to the unicode_script_subtag production of the unicode_language_id replaced by the string script.
+    // If region is not undefined, then
+    // If tag does not contain a unicode_region_subtag production of the unicode_language_id, then
+    // Set tag to the concatenation of the unicode_language_subtag production of the unicode_language_id of tag, the substring corresponding to the "-" unicode_script_subtag production of the unicode_language_id if present, "-", region, and the rest of tag.
+    // Else,
+    // Set tag to tag with the substring corresponding to the unicode_region_subtag production of the unicode_language_id replaced by the string region.
+    // Return CanonicalizeUnicodeLocaleId(tag).
+    std::string localeStr;
+
+    if (!language.isUndefined()) {
+        localeStr = language.asString()->toNonGCUTF8StringData();
+    } else {
+        localeStr = parsedResult.language;
+    }
+
+    if (!script.isUndefined()) {
+        localeStr += "-";
+        localeStr += script.asString()->toNonGCUTF8StringData();
+    } else if (parsedResult.script.length()) {
+        localeStr += "-";
+        localeStr += parsedResult.script;
+    }
+
+    if (!region.isUndefined()) {
+        localeStr += "-";
+        localeStr += region.asString()->toNonGCUTF8StringData();
+    } else if (parsedResult.region.length()) {
+        localeStr += "-";
+        localeStr += parsedResult.region;
+    }
+
+    for (size_t i = 0; i < parsedResult.variant.size(); i++) {
+        localeStr += "-";
+        localeStr += parsedResult.variant[i];
+    }
+
+    auto newParsedResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(localeStr);
+    if (!newParsedResult.canonicalizedTag) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
+    }
+
+    // We should not allow extlang here
+    if (newParsedResult.extLang.size()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "First argument of Intl.Locale should have valid tag");
+    }
+
+    newParsedResult.privateUse = parsedResult.privateUse;
+    newParsedResult.extensions = parsedResult.extensions;
+    newParsedResult.unicodeExtension = parsedResult.unicodeExtension;
+
+    return newParsedResult;
+}
+
+static bool checkOptionValueIsAlphaNum38DashAlphaNum38(const std::string& value)
+{
+    if (value.length() == 0) {
+        return false;
+    }
+
+    auto parts = split(value, '-');
+    if (parts.size() > 2) {
+        return false;
+    }
+    for (size_t i = 0; i < parts.size(); i++) {
+        const auto& s = parts[i];
+        if (s.length() < 3 || s.length() > 8 || !isAllSpecialCharacters(s, isASCIIAlphanumeric)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+IntlLocaleObject::IntlLocaleObject(ExecutionState& state, String* tag, Optional<Object*> options)
+    : IntlLocaleObject(state, state.context()->globalObject()->intlLocalePrototype(), tag, options)
+{
+}
+
+IntlLocaleObject::IntlLocaleObject(ExecutionState& state, Object* proto, String* tag, Optional<Object*> options)
+    : Object(state, proto)
+{
+    // Set tag to ? ApplyOptionsToTag(tag, options).
+    Intl::CanonicalizedLangunageTag buildResult = applyOptionsToTag(state, tag, options);
+    m_language = String::fromUTF8(buildResult.language.data(), buildResult.language.length());
+    m_script = String::fromUTF8(buildResult.script.data(), buildResult.script.length());
+    m_region = String::fromUTF8(buildResult.region.data(), buildResult.region.length());
+    m_baseName = buildResult.canonicalizedTag.value();
+
+    // Let opt be a new Record.
+    Optional<String*> ca;
+    Optional<String*> co;
+    Optional<String*> hc;
+    Optional<String*> nu;
+    Optional<String*> kf;
+    Optional<String*> kn;
+
+    auto& parsedUnicodeExtension = buildResult.unicodeExtension;
+    for (size_t i = 0; i < parsedUnicodeExtension.size(); i++) {
+        if (!ca && parsedUnicodeExtension[i].first == "ca") {
+            ca = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        } else if (!co && parsedUnicodeExtension[i].first == "co") {
+            co = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        } else if (!hc && parsedUnicodeExtension[i].first == "hc") {
+            hc = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        } else if (!kf && parsedUnicodeExtension[i].first == "kf") {
+            kf = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        } else if (!kn && parsedUnicodeExtension[i].first == "kn") {
+            kn = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        } else if (!nu && parsedUnicodeExtension[i].first == "nu") {
+            nu = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
+        }
+    }
+
+    // Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined).
+    String* calendarString = state.context()->staticStrings().calendar.string();
+    Value calendar = options ? Intl::getOption(state, options.value(), calendarString, Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If calendar is not undefined, then
+    if (!calendar.isUndefined()) {
+        // If calendar does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
+        // If calendar does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
+        std::string value = calendar.asString()->toNonGCUTF8StringData();
+        if (!uloc_toLegacyType("calendar", value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`calendar` option you input is not valid");
+        }
+        // Set opt.[[ca]] to calendar.
+        ca = calendar.asString();
+    }
+
+    // Let collation be ? GetOption(options, "collation", "string", undefined, undefined).
+    Value collation = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().collation.string(), Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If collation is not undefined, then
+    if (!collation.isUndefined()) {
+        // If collation does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
+        // If collation does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
+        std::string value = collation.asString()->toNonGCUTF8StringData();
+        if (!uloc_toLegacyType("collation", value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`collation` option you input is not valid");
+        }
+        // Set opt.[[co]] to collation.
+        co = collation.asString();
+    }
+
+
+    // Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
+    Value hourCycleValues[4] = { state.context()->staticStrings().lazyH11().string(), state.context()->staticStrings().lazyH12().string(), state.context()->staticStrings().lazyH23().string(), state.context()->staticStrings().lazyH24().string() };
+    Value hourCycle = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().hourCycle.string(), Intl::StringValue, hourCycleValues, 4, Value()) : Value();
+    // Set opt.[[hc]] to hc.
+    if (!hourCycle.isUndefined()) {
+        hc = hourCycle.asString();
+    }
+
+    // Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined).
+    Value caseFirstValues[3] = { state.context()->staticStrings().lazyUpper().string(), state.context()->staticStrings().lazyLower().string(), state.context()->staticStrings().stringFalse.string() };
+    // Set opt.[[kf]] to kf.
+    Value caseFirst = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().caseFirst.string(), Intl::StringValue, caseFirstValues, 3, Value()) : Value();
+    if (!caseFirst.isUndefined()) {
+        kf = caseFirst.asString();
+    }
+
+    // Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined).
+    Value numeric = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().numeric.string(), Intl::BooleanValue, nullptr, 0, Value()) : Value();
+    // If kn is not undefined, set kn to ! ToString(kn).
+    if (!numeric.isUndefined()) {
+        kn = numeric.toString(state);
+    }
+    // Set opt.[[kn]] to kn.
+
+    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
+    Value numberingSystem = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value()) : Value();
+    // If numberingSystem is not undefined, then
+    if (!numberingSystem.isUndefined()) {
+        // If numberingSystem does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
+        // If numberingSystem does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
+        std::string value = numberingSystem.asString()->toNonGCUTF8StringData();
+        if (!uloc_toLegacyType(uloc_toLegacyKey("nu"), value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`collation` option you input is not valid");
+        }
+        // Set opt.[[nu]] to numberingSystem.
+        nu = numberingSystem.asString();
+    }
+
+    // Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
+    m_calendar = ca;
+    m_caseFirst = kf;
+    m_collation = co;
+    m_hourCycle = hc;
+    m_numberingSystem = nu;
+    m_numeric = kn;
+
+    std::vector<std::pair<std::string, std::string>> newUnicodeExtension;
+    for (size_t i = 0; i < parsedUnicodeExtension.size(); i++) {
+        if (parsedUnicodeExtension[i].first != "ca" && parsedUnicodeExtension[i].first != "co" && parsedUnicodeExtension[i].first != "hc" && parsedUnicodeExtension[i].first != "kf" && parsedUnicodeExtension[i].first != "kn" && parsedUnicodeExtension[i].first != "nu") {
+            newUnicodeExtension.push_back(parsedUnicodeExtension[i]);
+        }
+    }
+
+    if (m_calendar) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("ca"), m_calendar->asString()->toNonGCUTF8StringData()));
+    }
+
+    if (m_caseFirst) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("kf"), m_caseFirst->asString()->equals("true") ? std::string() : m_caseFirst->asString()->toNonGCUTF8StringData()));
+    }
+
+    if (m_collation) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("co"), m_collation->asString()->toNonGCUTF8StringData()));
+    }
+
+    if (m_hourCycle) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("hc"), m_hourCycle->asString()->toNonGCUTF8StringData()));
+    }
+
+    if (m_numberingSystem) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("nu"), m_numberingSystem->asString()->toNonGCUTF8StringData()));
+    }
+
+    if (m_numeric) {
+        newUnicodeExtension.push_back(std::make_pair(std::string("kn"), m_numeric->asString()->equals("true") ? std::string() : m_numeric->asString()->toNonGCUTF8StringData()));
+    }
+
+    std::sort(newUnicodeExtension.begin(), newUnicodeExtension.end(),
+              [](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b) -> bool {
+                  return a.first < b.first;
+              });
+
+    StringBuilder localeBuilder;
+
+    localeBuilder.appendString(m_baseName);
+
+    size_t extensionIndex;
+    for (extensionIndex = 0; extensionIndex < buildResult.extensions.size(); extensionIndex++) {
+        if (buildResult.extensions[extensionIndex].key == 'u') {
+            extensionIndex++;
+            break;
+        }
+
+        localeBuilder.appendChar('-');
+        localeBuilder.appendChar(buildResult.extensions[extensionIndex].key);
+        localeBuilder.appendChar('-');
+        localeBuilder.appendString(buildResult.extensions[extensionIndex].value.data());
+    }
+
+    if (newUnicodeExtension.size()) {
+        localeBuilder.appendChar('-');
+        localeBuilder.appendChar('u');
+
+        for (size_t i = 0; i < newUnicodeExtension.size(); i++) {
+            if (newUnicodeExtension[i].first.length()) {
+                localeBuilder.appendChar('-');
+                localeBuilder.appendString(newUnicodeExtension[i].first.data());
+            }
+
+            if (newUnicodeExtension[i].second.length()) {
+                localeBuilder.appendChar('-');
+                localeBuilder.appendString(newUnicodeExtension[i].second.data());
+            }
+        }
+    }
+
+    for (; extensionIndex < buildResult.extensions.size(); extensionIndex++) {
+        localeBuilder.appendChar('-');
+        localeBuilder.appendChar(buildResult.extensions[extensionIndex].key);
+        localeBuilder.appendChar('-');
+        localeBuilder.appendString(buildResult.extensions[extensionIndex].value.data());
+    }
+
+    if (buildResult.privateUse.length()) {
+        localeBuilder.appendChar('-');
+        localeBuilder.appendString(buildResult.privateUse.data());
+    }
+
+    m_locale = localeBuilder.finalize();
+}
+
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlLocale.h
new file mode 100644 (file)
index 0000000..dca3eb5
--- /dev/null
@@ -0,0 +1,110 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlLocale__
+#define __EscargotIntlLocale__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlLocaleObject : public Object {
+public:
+    IntlLocaleObject(ExecutionState& state, String* tag, Optional<Object*> options);
+    IntlLocaleObject(ExecutionState& state, Object* proto, String* tag, Optional<Object*> options);
+
+    String* locale() const
+    {
+        return m_locale;
+    }
+
+    String* language() const
+    {
+        return m_language;
+    }
+
+    Value region() const
+    {
+        return m_region->length() ? Value(m_region) : Value();
+    }
+
+    Value script() const
+    {
+        return m_script->length() ? Value(m_script) : Value();
+    }
+
+    String* baseName() const
+    {
+        return m_baseName;
+    }
+
+    Optional<String*> calendar() const
+    {
+        return m_calendar;
+    }
+
+    Optional<String*> caseFirst() const
+    {
+        return m_caseFirst;
+    }
+
+    Optional<String*> collation() const
+    {
+        return m_collation;
+    }
+
+    Optional<String*> hourCycle() const
+    {
+        return m_hourCycle;
+    }
+
+    Optional<String*> numeric() const
+    {
+        return m_numeric;
+    }
+
+    Optional<String*> numberingSystem() const
+    {
+        return m_numberingSystem;
+    }
+
+    virtual bool isIntlLocaleObject() const override
+    {
+        return true;
+    }
+
+protected:
+    String* m_language;
+    String* m_script;
+    String* m_region;
+    String* m_baseName;
+    String* m_locale;
+    Optional<String*> m_calendar; // ca
+    Optional<String*> m_caseFirst; // kf
+    Optional<String*> m_collation; // co
+    Optional<String*> m_hourCycle; // hc
+    Optional<String*> m_numeric; // kn
+    Optional<String*> m_numberingSystem; // nu
+};
+
+} // namespace Escargot
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.cpp
new file mode 100644 (file)
index 0000000..21454f7
--- /dev/null
@@ -0,0 +1,935 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
+ * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/VMInstance.h"
+#include "Intl.h"
+#include "IntlNumberFormat.h"
+
+namespace Escargot {
+
+static const char* const intlNumberFormatRelevantExtensionKeys[1] = { "nu" };
+static const int intlNumberFormatRelevantExtensionKeysLength = 1;
+
+static size_t currencyDigits(String* currency)
+{
+    // https://www.currency-iso.org/en/home/tables/table-a1.html
+    // we should use ucurr_getDefaultFractionDigits but it returns wrong value for some contury
+    if (currency->equals("BHD")) {
+        return 3;
+    } else if (currency->equals("BIF")) {
+        return 0;
+    } else if (currency->equals("CLF")) {
+        return 4;
+    } else if (currency->equals("CLP")) {
+        return 0;
+    } else if (currency->equals("DJF")) {
+        return 0;
+    } else if (currency->equals("GNF")) {
+        return 0;
+    } else if (currency->equals("IQD")) {
+        return 3;
+    } else if (currency->equals("ISK")) {
+        return 0;
+    } else if (currency->equals("JOD")) {
+        return 3;
+    } else if (currency->equals("JPY")) {
+        return 0;
+    } else if (currency->equals("KMF")) {
+        return 0;
+    } else if (currency->equals("KRW")) {
+        return 0;
+    } else if (currency->equals("KWD")) {
+        return 3;
+    } else if (currency->equals("LYD")) {
+        return 3;
+    } else if (currency->equals("OMR")) {
+        return 3;
+    } else if (currency->equals("PYG")) {
+        return 0;
+    } else if (currency->equals("RWF")) {
+        return 0;
+    } else if (currency->equals("TND")) {
+        return 3;
+    } else if (currency->equals("UGX")) {
+        return 0;
+    } else if (currency->equals("UYI")) {
+        return 0;
+    } else if (currency->equals("UYW")) {
+        return 4;
+    } else if (currency->equals("VND")) {
+        return 0;
+    } else if (currency->equals("VUV")) {
+        return 0;
+    } else if (currency->equals("XAF")) {
+        return 0;
+    } else if (currency->equals("XOF")) {
+        return 0;
+    } else if (currency->equals("XPF")) {
+        return 0;
+    }
+
+    return 2;
+}
+
+static std::vector<std::string> localeDataNumberFormat(String* locale, size_t keyIndex)
+{
+    return Intl::numberingSystemsForLocale(locale);
+}
+
+static Value defaultNumberOption(ExecutionState& state, Value value, double minimum, double maximum, double fallback)
+{
+    // https://tc39.es/ecma402/#sec-defaultnumberoption
+    // If value is not undefined, then
+    if (!value.isUndefined()) {
+        // Let value be ToNumber(value).
+        double doubleValue = value.toNumber(state);
+        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
+        }
+        // Return floor(value).
+        return Value(floor(doubleValue));
+    } else {
+        // Else, return fallback.
+        return Value(fallback);
+    }
+}
+
+static double getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, double fallback)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
+
+    // Let value be the result of calling the [[Get]] internal method of options with argument property.
+    Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
+    // If value is not undefined, then
+    if (!value.isUndefined()) {
+        // Let value be ToNumber(value).
+        double doubleValue = value.toNumber(state);
+        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
+        }
+        // Return floor(value).
+        return floor(doubleValue);
+    } else {
+        // Else return fallback.
+        return fallback;
+    }
+}
+
+
+Object* IntlNumberFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
+{
+    Object* numberFormat = new Object(state, realm->globalObject()->intlNumberFormatPrototype());
+    initialize(state, numberFormat, locales, options);
+    return numberFormat;
+}
+
+// https://tc39.es/ecma402/#sec-issanctionedsimpleunitidentifier
+bool isSanctionedSimpleUnitIdentifier(const std::string& s)
+{
+    if (s == "acre") {
+        return true;
+    } else if (s == "bit") {
+        return true;
+    } else if (s == "byte") {
+        return true;
+    } else if (s == "celsius") {
+        return true;
+    } else if (s == "centimeter") {
+        return true;
+    } else if (s == "day") {
+        return true;
+    } else if (s == "degree") {
+        return true;
+    } else if (s == "fahrenheit") {
+        return true;
+    } else if (s == "fluid-ounce") {
+        return true;
+    } else if (s == "foot") {
+        return true;
+    } else if (s == "gallon") {
+        return true;
+    } else if (s == "gigabit") {
+        return true;
+    } else if (s == "gigabyte") {
+        return true;
+    } else if (s == "gram") {
+        return true;
+    } else if (s == "hectare") {
+        return true;
+    } else if (s == "hour") {
+        return true;
+    } else if (s == "inch") {
+        return true;
+    } else if (s == "kilobit") {
+        return true;
+    } else if (s == "kilobyte") {
+        return true;
+    } else if (s == "kilogram") {
+        return true;
+    } else if (s == "kilometer") {
+        return true;
+    } else if (s == "liter") {
+        return true;
+    } else if (s == "megabit") {
+        return true;
+    } else if (s == "megabyte") {
+        return true;
+    } else if (s == "meter") {
+        return true;
+    } else if (s == "mile") {
+        return true;
+    } else if (s == "mile-scandinavian") {
+        return true;
+    } else if (s == "milliliter") {
+        return true;
+    } else if (s == "millimeter") {
+        return true;
+    } else if (s == "millisecond") {
+        return true;
+    } else if (s == "minute") {
+        return true;
+    } else if (s == "month") {
+        return true;
+    } else if (s == "ounce") {
+        return true;
+    } else if (s == "percent") {
+        return true;
+    } else if (s == "petabyte") {
+        return true;
+    } else if (s == "pound") {
+        return true;
+    } else if (s == "second") {
+        return true;
+    } else if (s == "stone") {
+        return true;
+    } else if (s == "terabit") {
+        return true;
+    } else if (s == "terabyte") {
+        return true;
+    } else if (s == "week") {
+        return true;
+    } else if (s == "yard") {
+        return true;
+    } else if (s == "year") {
+        return true;
+    }
+    return false;
+}
+
+static bool isWellFormedUnitIdenifier(const std::string& s)
+{
+    // If the result of IsSanctionedSimpleUnitIdentifier(unitIdentifier) is true, then
+    // Return true.
+    if (isSanctionedSimpleUnitIdentifier(s)) {
+        return true;
+    }
+    // If the substring "-per-" does not occur exactly once in unitIdentifier, then
+    // Return false.
+    auto ss = split(s, "-per-");
+    if (ss.size() != 2) {
+        return false;
+    }
+    // Let numerator be the substring of unitIdentifier from the beginning to just before "-per-".
+    // If the result of IsSanctionedSimpleUnitIdentifier(numerator) is false, then
+    // Return false.
+    // Let denominator be the substring of unitIdentifier from just after "-per-" to the end.
+    // If the result of IsSanctionedSimpleUnitIdentifier(denominator) is false, then
+    // Return false.
+    // Return true.
+    return isSanctionedSimpleUnitIdentifier(ss[0]) && isSanctionedSimpleUnitIdentifier(ss[1]);
+}
+
+static const char* findICUUnitTypeFromUnitString(const std::string& s)
+{
+#define COMPARE_ONCE(to, from)                             \
+    if (memcmp(s.data(), #from, sizeof(#from) - 1) == 0) { \
+        return #to;                                        \
+    }
+    if (false) {
+    }
+    // clang-format off
+    COMPARE_ONCE(area, acre)
+    COMPARE_ONCE(digital, bit)
+    COMPARE_ONCE(digital, byte)
+    COMPARE_ONCE(temperature, celsius)
+    COMPARE_ONCE(length, centimeter)
+    COMPARE_ONCE(duration, day)
+    COMPARE_ONCE(angle, degree)
+    COMPARE_ONCE(temperature, fahrenheit)
+    COMPARE_ONCE(volume, fluid-ounce)
+    COMPARE_ONCE(length, foot)
+    COMPARE_ONCE(volume, gallon)
+    COMPARE_ONCE(digital, gigabit)
+    COMPARE_ONCE(digital, gigabyte)
+    COMPARE_ONCE(mass, gram)
+    COMPARE_ONCE(area, hectare)
+    COMPARE_ONCE(duration, hour)
+    COMPARE_ONCE(length, inch)
+    COMPARE_ONCE(digital, kilobit)
+    COMPARE_ONCE(digital, kilobyte)
+    COMPARE_ONCE(mass, kilogram)
+    COMPARE_ONCE(length, kilometer)
+    COMPARE_ONCE(volume, liter)
+    COMPARE_ONCE(digital, megabit)
+    COMPARE_ONCE(digital, megabyte)
+    COMPARE_ONCE(length, meter)
+    COMPARE_ONCE(length, mile)
+    COMPARE_ONCE(length, mile-scandinavian)
+    COMPARE_ONCE(volume, milliliter)
+    COMPARE_ONCE(length, millimeter)
+    COMPARE_ONCE(duration, millisecond)
+    COMPARE_ONCE(duration, minute)
+    COMPARE_ONCE(duration, month)
+    COMPARE_ONCE(mass, ounce)
+    COMPARE_ONCE(concentr, percent)
+    COMPARE_ONCE(digital, petabyte)
+    COMPARE_ONCE(mass, pound)
+    COMPARE_ONCE(duration, second)
+    COMPARE_ONCE(mass, stone)
+    COMPARE_ONCE(digital, terabit)
+    COMPARE_ONCE(digital, terabyte)
+    COMPARE_ONCE(duration, week)
+    COMPARE_ONCE(length, yard)
+    COMPARE_ONCE(duration, year)
+// clang-format on
+#undef COMPARE_ONCE
+    ASSERT_NOT_REACHED();
+
+    return "";
+}
+
+void IntlNumberFormat::initialize(ExecutionState& state, Object* numberFormat, Value locales, Value options)
+{
+#if defined(ENABLE_RUNTIME_ICU_BINDER)
+    UVersionInfo versionArray;
+    u_getVersion(versionArray);
+    if (versionArray[0] < 62) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.NumberFormat needs 62+ version of ICU");
+    }
+#endif
+
+    // If dateTimeFormat has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
+    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
+    if (numberFormat->hasInternalSlot() && numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
+    }
+
+    // Set the [[initializedIntlObject]] internal property of dateTimeFormat to true.
+    numberFormat->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state, initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
+
+    // Let requestedLocales be the result of calling the
+    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+
+    // If options is undefined, then
+    if (options.isUndefined()) {
+        // Let options be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.
+        options = new Object(state, Object::PrototypeIsNull);
+    } else {
+        // Else
+        // Let options be ToObject(options).
+        options = options.toObject(state);
+    }
+
+    // Let opt be a new Record.
+    StringMap opt;
+    // Let matcher be the result of calling the GetOption abstract operation (defined in 9.2.9) with the arguments options, "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit".
+    // Set opt.[[localeMatcher]] to matcher.
+    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
+    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
+    // Set opt.[[localeMatcher]] to matcher.
+    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
+
+    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
+    Value numberingSystem = Intl::getOption(state, options.asObject(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
+    // If numberingSystem is not undefined, then
+    if (!numberingSystem.isUndefined()) {
+        // If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
+        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
+        }
+    }
+    // Set opt.[[nu]] to numberingSystem.
+    if (!numberingSystem.isUndefined()) {
+        opt.insert(std::make_pair("nu", numberingSystem.asString()));
+    }
+
+    // Let NumberFormat be the standard built-in object that is the initial value of Intl.NumberFormat.
+    // Let localeData be the value of the [[localeData]] internal property of NumberFormat.
+    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the [[availableLocales]]
+    // internal property of NumberFormat, requestedLocales, opt, the [[relevantExtensionKeys]] internal property of NumberFormat, and localeData.
+    StringMap r = Intl::resolveLocale(state, state.context()->vmInstance()->intlNumberFormatAvailableLocales(), requestedLocales, opt, intlNumberFormatRelevantExtensionKeys, intlNumberFormatRelevantExtensionKeysLength, localeDataNumberFormat);
+
+    // Set the [[locale]] internal property of numberFormat to the value of r.[[locale]].
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), numberFormat->internalSlot());
+    // Set numberFormat.[[DataLocale]] to r.[[dataLocale]].
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDataLocale()), r.at("dataLocale"), numberFormat->internalSlot());
+    // Set the [[numberingSystem]] internal property of numberFormat to the value of r.[[nu]].
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), r.at("nu"), numberFormat->internalSlot());
+
+    // SetNumberFormatUnitOptions ( intlObj, options )
+    // Let s be the result of calling the GetOption abstract operation with the arguments options, "style", "string",
+    // a List containing the three String values "decimal", "percent", and "currency", and "decimal".
+    Value styleValues[4] = { state.context()->staticStrings().lazyDecimal().string(), state.context()->staticStrings().lazyPercent().string(), state.context()->staticStrings().lazyCurrency().string(), state.context()->staticStrings().lazyUnit().string() };
+    Value style = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyStyle().string(), Intl::StringValue, styleValues, 4, styleValues[0]);
+
+    // Set the [[style]] internal property of numberFormat to s.
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyStyle()), style, numberFormat->internalSlot());
+
+    // Let currency be the result of calling the GetOption abstract operation with the arguments options, "currency", "string", undefined, and undefined.
+    Value currency = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrency().string(), Intl::StringValue, nullptr, 0, Value());
+    // If currency is not undefined and the result of calling the IsWellFormedCurrencyCode abstract operation (defined in 6.3.1) with argument c is false, then throw a RangeError exception.
+    if (!currency.isUndefined()) {
+        String* currencyString = currency.asString();
+        UTF8StringDataNonGCStd cc = currencyString->toUTF8StringData().data();
+        if (currencyString->length() != 3 || !isAllSpecialCharacters(cc, isASCIIAlpha)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "currency is not a well-formed currency code");
+        }
+    }
+
+    // If style is "currency" and currency is undefined, throw a TypeError exception.
+    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string()) && currency.isUndefined()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "if style option is `currency`, you must specify currency");
+    }
+
+    // Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
+    Value currencyDisplayValues[4] = { state.context()->staticStrings().lazyCode().string(), state.context()->staticStrings().symbol.string(), state.context()->staticStrings().lazyNarrowSymbol().string(), state.context()->staticStrings().name.string() };
+    Value currencyDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrencyDisplay().string(), Intl::StringValue, currencyDisplayValues, 4, currencyDisplayValues[1]);
+    // Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard").
+    Value currencySignValues[2] = { state.context()->staticStrings().lazyStandard().string(), state.context()->staticStrings().lazyAccounting().string() };
+    Value currencySign = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrencySign().string(), Intl::StringValue, currencySignValues, 2, currencySignValues[0]);
+    // Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
+    Value unit = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUnit().string(), Intl::StringValue, nullptr, 0, Value());
+    if (!unit.isUndefined()) {
+        String* unitString = unit.asString();
+        UTF8StringDataNonGCStd cc = unitString->toUTF8StringData().data();
+        if (!isWellFormedUnitIdenifier(cc)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is not a well-formed unit idenitfier");
+        }
+    }
+
+    // If style is "unit" and unit is undefined, throw a TypeError exception.
+    if (style.equalsTo(state, state.context()->staticStrings().lazyUnit().string()) && unit.isUndefined()) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "if style option is `unit`, you must specify unit");
+    }
+
+    // Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
+    Value unitDisplayValues[3] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyLong().string() };
+    Value unitDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUnitDisplay().string(), Intl::StringValue, unitDisplayValues, 3, unitDisplayValues[0]);
+
+    // If style is "currency", then
+    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
+        // Let currency be the result of converting currency to upper case as specified in 6.1.
+        String* cString = currency.toString(state);
+        std::string str = cString->toUTF8StringData().data();
+        std::transform(str.begin(), str.end(), str.begin(), toupper);
+        currency = String::fromASCII(str.data(), str.length());
+        // Set intlObj.[[Currency]] to currency.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrency()), currency, numberFormat->internalSlot());
+        // Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrencyDisplay()), currencyDisplay.asString(), numberFormat->internalSlot());
+        // Set intlObj.[[CurrencySign]] to currencySign.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrencySign()), currencySign.asString(), numberFormat->internalSlot());
+    }
+
+    // If style is "unit", then
+    if (style.equalsTo(state, state.context()->staticStrings().lazyUnit().string())) {
+        // Set intlObj.[[Unit]] to unit.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUnit()), unit.asString(), numberFormat->internalSlot());
+        // Set intlObj.[[UnitDisplay]] to unitDisplay.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUnitDisplay()), unitDisplay.asString(), numberFormat->internalSlot());
+    }
+
+    double mnfdDefault = 0;
+    double mxfdDefault = 0;
+
+    // Let style be numberFormat.[[Style]].
+    // If style is "currency", then
+    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
+        // Let currency be numberFormat.[[Currency]].
+        // Let cDigits be CurrencyDigits(currency).
+        size_t cDigits = currencyDigits(currency.asString());
+        // Let mnfdDefault be cDigits.
+        mnfdDefault = cDigits;
+        // Let mxfdDefault be cDigits.
+        mxfdDefault = cDigits;
+    } else {
+        // Else,
+        // Let mnfdDefault be 0.
+        mnfdDefault = 0;
+        // If style is "percent", then
+        if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
+            // Let mxfdDefault be 0.
+            mxfdDefault = 0;
+        } else {
+            // Else,
+            // Let mxfdDefault be 3.
+            mxfdDefault = 3;
+        }
+    }
+
+    // Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
+    Value notationValues[4] = { state.context()->staticStrings().lazyStandard().string(), state.context()->staticStrings().lazyScientific().string(), state.context()->staticStrings().lazyEngineering().string(), state.context()->staticStrings().lazyCompact().string() };
+    Value notation = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyNotation().string(), Intl::StringValue, notationValues, 4, notationValues[0]);
+    // Set numberFormat.[[Notation]] to notation.
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyNotation()), notation, numberFormat->internalSlot());
+
+    // Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
+    // Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1).
+    double mnid = getNumberOption(state, options.asObject(), state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
+    // Let mnfd be ? Get(options, "minimumFractionDigits").
+    Value mnfd;
+    auto g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()));
+    if (g.hasValue()) {
+        mnfd = g.value(state, options.asObject());
+    }
+    // Let mxfd be ? Get(options, "maximumFractionDigits").
+    Value mxfd;
+    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()));
+    if (g.hasValue()) {
+        mxfd = g.value(state, options.asObject());
+    }
+    // Let mnsd be ? Get(options, "minimumSignificantDigits").
+    Value mnsd;
+    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()));
+    if (g.hasValue()) {
+        mnsd = g.value(state, options.asObject());
+    }
+    // Let mxsd be ? Get(options, "maximumSignificantDigits").
+    Value mxsd;
+    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()));
+    if (g.hasValue()) {
+        mxsd = g.value(state, options.asObject());
+    }
+
+    // Set intlObj.[[MinimumIntegerDigits]] to mnid.
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits()), Value(mnid), numberFormat->internalSlot());
+
+    // If mnsd is not undefined or mxsd is not undefined, then
+    if (!mnsd.isUndefined() || !mxsd.isUndefined()) {
+        // Set intlObj.[[RoundingType]] to significantDigits.
+        // Let mnsd be ? DefaultNumberOption(mnsd, 1, 21, 1).
+        mnsd = defaultNumberOption(state, mnsd, 1, 21, 1);
+        // Let mxsd be ? DefaultNumberOption(mxsd, mnsd, 21, 21).
+        mxsd = defaultNumberOption(state, mxsd, mnsd.asNumber(), 21, 21);
+        // Set intlObj.[[MinimumSignificantDigits]] to mnsd.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()), mnsd, numberFormat->internalSlot());
+        // Set intlObj.[[MaximumSignificantDigits]] to mxsd.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()), mxsd, numberFormat->internalSlot());
+    } else if (!mnfd.isUndefined() || !mxfd.isUndefined()) {
+        // Else if mnfd is not undefined or mxfd is not undefined, then
+        // Set intlObj.[[RoundingType]] to fractionDigits.
+        // Let mnfd be ? DefaultNumberOption(mnfd, 0, 20, mnfdDefault).
+        mnfd = defaultNumberOption(state, mnfd, 0, 20, mnfdDefault);
+        // Let mxfdActualDefault be max( mnfd, mxfdDefault ).
+        double mxfdActualDefault = std::max(mnfd.asNumber(), mxfdDefault);
+        // Let mxfd be ? DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault).
+        mxfd = defaultNumberOption(state, mxfd, mnfd.asNumber(), 20, mxfdActualDefault);
+        // Set intlObj.[[MinimumFractionDigits]] to mnfd.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), mnfd, numberFormat->internalSlot());
+        // Set intlObj.[[MaximumFractionDigits]] to mxfd.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), mxfd, numberFormat->internalSlot());
+    } else if (notation.equalsTo(state, state.context()->staticStrings().lazyCompact().string())) {
+        // Else if notation is "compact", then
+        // Set intlObj.[[RoundingType]] to compactRounding.
+    } else {
+        // Set intlObj.[[RoundingType]] to fractionDigits.
+        // Set intlObj.[[MinimumFractionDigits]] to mnfdDefault.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), Value(mnfdDefault), numberFormat->internalSlot());
+        // Set intlObj.[[MaximumFractionDigits]] to mxfdDefault.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), Value(mxfdDefault), numberFormat->internalSlot());
+    }
+
+    // Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
+    Value compactDisplayValues[2] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
+    Value compactDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCompactDisplay().string(), Intl::StringValue, compactDisplayValues, 2, compactDisplayValues[0]);
+
+    // If notation is "compact", then
+    if (notation.equalsTo(state, state.context()->staticStrings().lazyCompact().string())) {
+        // Set numberFormat.[[CompactDisplay]] to compactDisplay.
+        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCompactDisplay()), compactDisplay, numberFormat->internalSlot());
+    }
+
+    // Let useGrouping be ? GetOption(options, "useGrouping", "boolean", undefined, true).
+    Value useGrouping = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUseGrouping().string(), Intl::BooleanValue, nullptr, 0, Value(true));
+    // Set numberFormat.[[UseGrouping]] to useGrouping.
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUseGrouping()), useGrouping, numberFormat->internalSlot());
+
+    // Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto").
+    Value signDisplayValue[4] = { state.context()->staticStrings().lazyAuto().string(), state.context()->staticStrings().lazyNever().string(), state.context()->staticStrings().lazyAlways().string(), state.context()->staticStrings().lazyExceptZero().string() };
+    Value signDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazySignDisplay().string(), Intl::StringValue, signDisplayValue, 4, signDisplayValue[0]);
+    // Set numberFormat.[[SignDisplay]] to signDisplay.
+    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySignDisplay()), signDisplay, numberFormat->internalSlot());
+
+    // Set the [[initializedNumberFormat]] internal property of numberFormat to true.
+    numberFormat->internalSlot()->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()), ObjectPropertyDescriptor(Value(true)));
+    // Return numberFormat
+
+    UTF16StringDataNonGCStd skeleton;
+
+    if (style.asString()->equals("currency")) {
+        if (!currency.isUndefined()) {
+            skeleton += u"currency/";
+            skeleton += currency.asString()->charAt(0);
+            skeleton += currency.asString()->charAt(1);
+            skeleton += currency.asString()->charAt(2);
+            skeleton += u" ";
+        }
+
+        if (currencyDisplay.asString()->equals("code")) {
+            skeleton += u"unit-width-iso-code ";
+        } else if (currencyDisplay.asString()->equals("symbol")) {
+            // default
+        } else if (currencyDisplay.asString()->equals("narrowSymbol")) {
+            skeleton += u"unit-width-narrow ";
+        } else if (currencyDisplay.asString()->equals("name")) {
+            skeleton += u"unit-width-full-name ";
+        } else {
+            ASSERT_NOT_REACHED();
+        }
+    } else if (style.asString()->equals("percent")) {
+        skeleton += u"percent scale/100 ";
+    } else if (style.asString()->equals("unit")) {
+        String* unitString = unit.asString();
+        if (unitString->contains("-per-")) {
+            size_t pos = unitString->find("-per-");
+            skeleton += u"measure-unit/";
+            const char* u = findICUUnitTypeFromUnitString(unitString->substring(0, pos)->toNonGCUTF8StringData());
+            size_t len = strlen(u);
+            for (size_t i = 0; i < len; i++) {
+                skeleton += u[i];
+            }
+            skeleton += '-';
+            skeleton += unitString->substring(0, pos)->toUTF16StringData().data();
+            skeleton += ' ';
+
+            skeleton += u"per-measure-unit/";
+            u = findICUUnitTypeFromUnitString(unitString->substring(pos + 5, unitString->length())->toNonGCUTF8StringData());
+            len = strlen(u);
+            for (size_t i = 0; i < len; i++) {
+                skeleton += u[i];
+            }
+            skeleton += '-';
+            skeleton += unitString->substring(pos + 5, unitString->length())->toUTF16StringData().data();
+            skeleton += ' ';
+        } else {
+            skeleton += u"measure-unit/";
+            const char* u = findICUUnitTypeFromUnitString(unitString->toNonGCUTF8StringData());
+            size_t len = strlen(u);
+            for (size_t i = 0; i < len; i++) {
+                skeleton += u[i];
+            }
+            skeleton += '-';
+            skeleton += unitString->toUTF16StringData().data();
+            skeleton += ' ';
+        }
+
+        String* unitDisplayString = unitDisplay.asString();
+        if (unitDisplayString->equals("short")) {
+            skeleton += u"unit-width-short ";
+        } else if (unitDisplayString->equals("narrow")) {
+            skeleton += u"unit-width-narrow ";
+        } else {
+            ASSERT(unitDisplayString->equals("long"));
+            skeleton += u"unit-width-full-name ";
+        }
+    }
+
+    if (numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()))) {
+        double mnsd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
+        double mxsd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
+
+        for (double i = 0; i < mnsd; i++) {
+            skeleton += '@';
+        }
+
+        for (double i = 0; i < mxsd - mnsd; i++) {
+            skeleton += '#';
+        }
+
+        skeleton += ' ';
+    }
+
+    if (numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()))) {
+        double mnfd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
+        double mxfd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
+
+        skeleton += '.';
+
+        for (double i = 0; i < mnfd; i++) {
+            skeleton += '0';
+        }
+
+        for (double i = 0; i < mxfd - mnfd; i++) {
+            skeleton += '#';
+        }
+        skeleton += ' ';
+    }
+
+    {
+        double mnid = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
+        skeleton += u"integer-width/+";
+        for (double i = 0; i < mnid; i++) {
+            skeleton += '0';
+        }
+        skeleton += ' ';
+    }
+
+    if (!useGrouping.asBoolean()) {
+        skeleton += u"group-off ";
+    }
+
+    String* notationString = notation.asString();
+    if (notationString->equals("standard")) {
+    } else if (notationString->equals("scientific")) {
+        skeleton += u"scientific ";
+    } else if (notationString->equals("engineering")) {
+        skeleton += u"engineering ";
+    } else {
+        if (compactDisplay.asString()->equals("short")) {
+            skeleton += u"compact-short ";
+        } else {
+            skeleton += u"compact-long ";
+        }
+    }
+
+    String* signDisplayString = signDisplay.asString();
+    bool accountingSign = currencySign.asString()->equals("accounting");
+    if (signDisplayString->equals("auto")) {
+        if (accountingSign) {
+            skeleton += u"sign-accounting ";
+        }
+    } else if (signDisplayString->equals("never")) {
+        skeleton += u"sign-never ";
+    } else if (signDisplayString->equals("always")) {
+        if (accountingSign) {
+            skeleton += u"sign-accounting-always ";
+        } else {
+            skeleton += u"sign-always ";
+        }
+    } else {
+        if (accountingSign) {
+            skeleton += u"sign-accounting-except-zero ";
+        } else {
+            skeleton += u"sign-except-zero ";
+        }
+    }
+
+    skeleton += u"rounding-mode-half-up ";
+
+    String* localeOption = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale())).value(state, numberFormat->internalSlot()).toString(state);
+
+    UErrorCode status = U_ZERO_ERROR;
+    UNumberFormatter* fomatter = unumf_openForSkeletonAndLocale((UChar*)skeleton.data(), skeleton.length(), localeOption->toNonGCUTF8StringData().data(), &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init NumberFormat");
+    }
+
+    numberFormat->internalSlot()->setExtraData(fomatter);
+
+    numberFormat->internalSlot()->addFinalizer([](Object* obj, void* data) {
+        Object* self = (Object*)obj;
+        unumf_close((UNumberFormatter*)self->extraData());
+    },
+                                               nullptr);
+}
+
+UTF16StringDataNonGCStd IntlNumberFormat::format(ExecutionState& state, Object* numberFormat, double x)
+{
+    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
+
+    UErrorCode status = U_ZERO_ERROR;
+    UTF16StringDataNonGCStd resultString;
+
+    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
+
+    unumf_formatDouble(formatter, x, uresult.get(), &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    resultString.resize(32);
+    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    resultString.resize(length);
+
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    }
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    return resultString;
+}
+
+UTF16StringDataNonGCStd IntlNumberFormat::format(ExecutionState& state, Object* numberFormat, String* str)
+{
+    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
+
+    UErrorCode status = U_ZERO_ERROR;
+    UTF16StringDataNonGCStd resultString;
+
+    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
+
+    auto s = str->toNonGCUTF8StringData();
+
+    unumf_formatDecimal(formatter, s.data(), s.length(), uresult.get(), &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    resultString.resize(32);
+    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    resultString.resize(length);
+
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    }
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    return resultString;
+}
+
+ArrayObject* IntlNumberFormat::formatToParts(ExecutionState& state, Object* numberFormat, double x)
+{
+    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
+
+    ArrayObject* result = new ArrayObject(state);
+
+    UErrorCode status = U_ZERO_ERROR;
+    UTF16StringDataNonGCStd resultString;
+
+    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
+
+    unumf_formatDouble(formatter, x, uresult.get(), &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    resultString.resize(32);
+    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    resultString.resize(length);
+
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        status = U_ZERO_ERROR;
+        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
+    }
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    LocalResourcePointer<UFieldPositionIterator> fpositer(ufieldpositer_open(&status), [](UFieldPositionIterator* f) { ufieldpositer_close(f); });
+    ASSERT(U_SUCCESS(status));
+
+    unumf_resultGetAllFieldPositions(uresult.get(), fpositer.get(), &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
+    }
+
+    std::vector<Intl::NumberFieldItem> fields;
+
+    while (true) {
+        int32_t start;
+        int32_t end;
+        int32_t type = ufieldpositer_next(fpositer.get(), &start, &end);
+        if (type < 0) {
+            break;
+        }
+
+        if (std::isnan(x) || std::isinf(x)) {
+            // We should ignore `E0` field of NaN, Infinity
+            // NaNE0->NaN
+            if (type == UNUM_EXPONENT_SYMBOL_FIELD) {
+                continue;
+            }
+            if (type == UNUM_EXPONENT_FIELD) {
+                continue;
+            }
+        }
+
+        Intl::NumberFieldItem item;
+        item.start = start;
+        item.end = end;
+        item.type = type;
+
+        fields.push_back(item);
+    }
+
+    Intl::convertICUNumberFieldToEcmaNumberField(fields, x, resultString);
+
+    AtomicString typeAtom(state, "type", 4);
+    AtomicString valueAtom = state.context()->staticStrings().value;
+
+    for (size_t i = 0; i < fields.size(); i++) {
+        const Intl::NumberFieldItem& item = fields[i];
+
+        Object* o = new Object(state);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(Intl::icuNumberFieldToString(state, item.type, x), ObjectPropertyDescriptor::AllPresent));
+        auto sub = resultString.substr(item.start, item.end - item.start);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
+
+        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
+    }
+
+    return result;
+}
+
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlNumberFormat.h
new file mode 100644 (file)
index 0000000..37fb841
--- /dev/null
@@ -0,0 +1,40 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2019-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlNumberFormat__
+#define __EscargotIntlNumberFormat__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlNumberFormat {
+public:
+    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
+    static void initialize(ExecutionState& state, Object* numberFormat, Value locales, Value options);
+    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* numberFormat, double x);
+    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* numberFormat, String* str);
+    static ArrayObject* formatToParts(ExecutionState& state, Object* numberFormat, double x);
+};
+
+} // namespace Escargot
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.cpp
new file mode 100644 (file)
index 0000000..5561740
--- /dev/null
@@ -0,0 +1,223 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "runtime/VMInstance.h"
+#include "Intl.h"
+#include "IntlPluralRules.h"
+
+namespace Escargot {
+
+static double getNumberOption(ExecutionState& state, Optional<Object*> options, String* property, double minimum, double maximum, double fallback)
+{
+    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
+    if (!options) {
+        return fallback;
+    }
+
+    // Let value be the result of calling the [[Get]] internal method of options with argument property.
+    Value value = options.value()->get(state, ObjectPropertyName(state, property)).value(state, options.value());
+    // If value is not undefined, then
+    if (!value.isUndefined()) {
+        // Let value be ToNumber(value).
+        double doubleValue = value.toNumber(state);
+        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
+        }
+        // Return floor(value).
+        return floor(doubleValue);
+    } else {
+        // Else return fallback.
+        return fallback;
+    }
+}
+
+void* IntlPluralRulesObject::operator new(size_t size)
+{
+    static MAY_THREAD_LOCAL bool typeInited = false;
+    static MAY_THREAD_LOCAL GC_descr descr;
+    if (!typeInited) {
+        GC_word desc[GC_BITMAP_SIZE(IntlPluralRulesObject)] = { 0 };
+        Object::fillGCDescriptor(desc);
+        GC_set_bit(desc, GC_WORD_OFFSET(IntlPluralRulesObject, m_locale));
+        GC_set_bit(desc, GC_WORD_OFFSET(IntlPluralRulesObject, m_type));
+        descr = GC_make_descriptor(desc, GC_WORD_LEN(IntlPluralRulesObject));
+        typeInited = true;
+    }
+    return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
+}
+
+IntlPluralRulesObject::IntlPluralRulesObject(ExecutionState& state, Object* proto, Value locales, Value options)
+    : Object(state, proto)
+    , m_icuPluralRules(nullptr)
+    , m_icuNumberFormat(nullptr)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-initializepluralrules
+    // [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]
+
+    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+
+    Optional<Object*> optionObject;
+    // If options is undefined, then
+    if (options.isUndefined()) {
+        // Let options be ObjectCreate(null).
+    } else {
+        // Let options be ? ToObject(options).
+        optionObject = options.toObject(state);
+    }
+
+    // Let opt be a new Record.
+    StringMap opt;
+    // Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
+    // Set opt.[[localeMatcher]] to matcher.
+    Value localeMatcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
+    String* matcher = localeMatcherValues[1].asString();
+    if (optionObject) {
+        matcher = Intl::getOption(state, optionObject.value(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, localeMatcherValues, 2, localeMatcherValues[1]).asString();
+    }
+    opt.insert(std::make_pair("matcher", matcher));
+
+    // Let t be ? GetOption(options, "type", "string", « "cardinal", "ordinal" », "cardinal").
+    Value typeValues[2] = { state.context()->staticStrings().lazyCardinal().string(), state.context()->staticStrings().lazyOrdinal().string() };
+    String* t = typeValues[0].asString();
+    if (optionObject) {
+        t = Intl::getOption(state, optionObject.value(), state.context()->staticStrings().lazyType().string(), Intl::StringValue, typeValues, 2, typeValues[0]).asString();
+    }
+
+    // Perform ? SetNumberFormatDigitOptions(pluralRules, options, 0, 3).
+    // Let mnid be the result of calling the GetNumberOption abstract operation (defined in 9.2.10) with arguments options, "minimumIntegerDigits", 1, 21, and 1.
+    double mnid = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
+    // Set the [[minimumIntegerDigits]] internal property of numberFormat to mnid.
+    m_minimumIntegerDigits = mnid;
+
+    double mnfdDefault = 0;
+    // Let mnfd be the result of calling the GetNumberOption abstract operation with arguments options, "minimumFractionDigits", 0, 20, and mnfdDefault.
+    double mnfd = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMinimumFractionDigits().string(), 0, 20, mnfdDefault);
+
+    // Set the [[minimumFractionDigits]] internal property of numberFormat to mnfd.
+    m_minimumFractionDigits = mnfd;
+
+    double mxfdDefault = 3;
+
+    // Let mxfd be the result of calling the GetNumberOption abstract operation with arguments options, "maximumFractionDigits", mnfd, 20, and mxfdDefault.
+    double mxfd = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMaximumFractionDigits().string(), mnfd, 20, mxfdDefault);
+
+    // Set the [[maximumFractionDigits]] internal property of numberFormat to mxfd.
+    m_maximumFractionDigits = mxfd;
+
+    if (optionObject) {
+        // Let mnsd be the result of calling the [[Get]] internal method of options with argument "minimumSignificantDigits".
+        Value mnsd = optionObject.value()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits())).value(state, optionObject.value());
+        // Let mxsd be the result of calling the [[Get]] internal method of options with argument "maximumSignificantDigits".
+        Value mxsd = optionObject.value()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits())).value(state, optionObject.value());
+
+        // If mnsd is not undefined or mxsd is not undefined, then:
+        if (!mnsd.isUndefined() || !mxsd.isUndefined()) {
+            // Let mnsd be the result of calling the GetNumberOption abstract operation with arguments options, "minimumSignificantDigits", 1, 21, and 1.
+            mnsd = Value(getNumberOption(state, optionObject.value(), state.context()->staticStrings().lazyMinimumSignificantDigits().string(), 1, 21, 1));
+            // Let mxsd be the result of calling the GetNumberOption abstract operation with arguments options, "maximumSignificantDigits", mnsd, 21, and 21.
+            mxsd = Value(getNumberOption(state, optionObject.value(), state.context()->staticStrings().lazyMaximumSignificantDigits().string(), mnsd.asNumber(), 21, 21));
+            // Set the [[minimumSignificantDigits]] internal property of numberFormat to mnsd,
+            // and the [[maximumSignificantDigits]] internal property of numberFormat to mxsd.
+            m_minimumSignificantDigits = mnsd.asNumber();
+            m_maximumSignificantDigits = mxsd.asNumber();
+        }
+    }
+
+    // Let localeData be %PluralRules%.[[LocaleData]].
+    // Let r be ResolveLocale(%PluralRules%.[[AvailableLocales]], requestedLocales, opt, %PluralRules%.[[RelevantExtensionKeys]], localeData).
+    // Set pluralRules.[[Locale]] to the value of r.[[locale]].
+    auto r = Intl::resolveLocale(state, state.context()->vmInstance()->intlPluralRulesAvailableLocales(), requestedLocales, opt, nullptr, 0, nullptr);
+    String* foundLocale = r.at("locale");
+
+    UErrorCode status = U_ZERO_ERROR;
+    m_icuNumberFormat = unum_open(UNUM_DEFAULT, nullptr, 0, foundLocale->toNonGCUTF8StringData().data(), nullptr, &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init PluralRule");
+    }
+
+    if (!m_minimumSignificantDigits.hasValue()) {
+        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits);
+        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits);
+        unum_setAttribute(m_icuNumberFormat, UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits);
+    } else {
+        unum_setAttribute(m_icuNumberFormat, UNUM_SIGNIFICANT_DIGITS_USED, true);
+        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits);
+        unum_setAttribute(m_icuNumberFormat, UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits);
+    }
+    unum_setAttribute(m_icuNumberFormat, UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init NumberFormat");
+    }
+
+    ASSERT(U_SUCCESS(status));
+
+    UPluralType icuType = UPLURAL_TYPE_CARDINAL;
+    if (t->equals("ordinal")) {
+        icuType = UPLURAL_TYPE_ORDINAL;
+    }
+
+    m_icuPluralRules = uplrules_openForType(foundLocale->toNonGCUTF8StringData().data(), icuType, &status);
+    if (!m_icuPluralRules) {
+        auto parseResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(foundLocale->toNonGCUTF8StringData());
+        // Remove extensions and try again.
+        m_icuPluralRules = uplrules_openForType(parseResult.language.data(), icuType, &status);
+        ASSERT(U_SUCCESS(status));
+    }
+
+    m_locale = foundLocale;
+    m_type = t;
+
+    addFinalizer([](Object* obj, void* data) {
+        IntlPluralRulesObject* self = (IntlPluralRulesObject*)obj;
+        uplrules_close(self->m_icuPluralRules);
+        unum_close(self->m_icuNumberFormat);
+    },
+                 nullptr);
+
+    // Return pluralRules.
+}
+
+String* IntlPluralRulesObject::resolvePlural(double number)
+{
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-resolveplural
+    // If n is not a finite Number, then
+    if (std::isinf(number)) {
+        // Return "other".
+        return String::fromASCII("other");
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t len = uplrules_selectWithFormat(m_icuPluralRules, number, m_icuNumberFormat, nullptr, 0, &status);
+    UChar* buf = (UChar*)alloca((len + 1) * sizeof(UChar));
+    status = U_ZERO_ERROR;
+    uplrules_selectWithFormat(m_icuPluralRules, number, m_icuNumberFormat, buf, len + 1, &status);
+    ASSERT(U_SUCCESS(status));
+
+    return new UTF16String(buf, len);
+}
+
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlPluralRules.h
new file mode 100644 (file)
index 0000000..99cb8eb
--- /dev/null
@@ -0,0 +1,104 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlPluralRules__
+#define __EscargotIntlPluralRules__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlPluralRulesObject : public Object {
+public:
+    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl-pluralrules-constructor
+    IntlPluralRulesObject(ExecutionState& state, Object* proto, Value locales, Value options);
+
+    virtual bool isIntlPluralRulesObject() const override
+    {
+        return true;
+    }
+
+    String* resolvePlural(double number);
+
+    String* locale() const
+    {
+        return m_locale;
+    }
+
+    String* type() const
+    {
+        return m_type;
+    }
+
+    double minimumIntegerDigits() const
+    {
+        return m_minimumIntegerDigits;
+    }
+
+    double minimumFractionDigits() const
+    {
+        return m_minimumFractionDigits;
+    }
+
+    double maximumFractionDigits() const
+    {
+        return m_maximumFractionDigits;
+    }
+
+    Optional<double> minimumSignificantDigits() const
+    {
+        return m_minimumSignificantDigits;
+    }
+
+    Optional<double> maximumSignificantDigits() const
+    {
+        return m_maximumSignificantDigits;
+    }
+
+    UPluralRules* icuPluralRules() const
+    {
+        return m_icuPluralRules;
+    }
+
+    UNumberFormat* icuNumberFormat() const
+    {
+        return m_icuNumberFormat;
+    }
+
+    void* operator new(size_t size);
+    void* operator new[](size_t size) = delete;
+
+protected:
+    String* m_locale;
+    String* m_type;
+    double m_minimumIntegerDigits;
+    double m_minimumFractionDigits;
+    double m_maximumFractionDigits;
+    Optional<double> m_minimumSignificantDigits;
+    Optional<double> m_maximumSignificantDigits;
+
+    UPluralRules* m_icuPluralRules;
+    UNumberFormat* m_icuNumberFormat;
+};
+
+} // namespace Escargot
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.cpp
new file mode 100644 (file)
index 0000000..a4619fa
--- /dev/null
@@ -0,0 +1,352 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Context.h"
+#include "runtime/ExecutionState.h"
+#include "runtime/Value.h"
+#include "runtime/DateObject.h"
+#include "runtime/ArrayObject.h"
+#include "runtime/VMInstance.h"
+#include "Intl.h"
+#include "IntlRelativeTimeFormat.h"
+
+namespace Escargot {
+
+static const char* const intlRelativeTimeFormatRelevantExtensionKeys[1] = { "nu" };
+static size_t intlRelativeTimeFormatRelevantExtensionKeysLength = 1;
+static const size_t indexOfExtensionKeyNu = 0;
+
+static std::vector<std::string> localeDataRelativeTimeFormat(String* locale, size_t keyIndex)
+{
+    std::vector<std::string> keyLocaleData;
+    switch (keyIndex) {
+    case indexOfExtensionKeyNu:
+        keyLocaleData = Intl::numberingSystemsForLocale(locale);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return keyLocaleData;
+}
+
+IntlRelativeTimeFormatObject::IntlRelativeTimeFormatObject(ExecutionState& state, Value locales, Value options)
+    : IntlRelativeTimeFormatObject(state, state.context()->globalObject()->intlRelativeTimeFormatPrototype(), locales, options)
+{
+}
+
+IntlRelativeTimeFormatObject::IntlRelativeTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value optionsInput)
+    : Object(state, proto)
+{
+#if defined(ENABLE_RUNTIME_ICU_BINDER)
+    UVersionInfo versionArray;
+    u_getVersion(versionArray);
+    if (versionArray[0] < 62) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.NumberFormat needs 62+ version of ICU");
+    }
+#endif
+    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
+    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+
+    Optional<Object*> options;
+    // If options is undefined, then
+    if (optionsInput.isUndefined()) {
+        // Let options be ObjectCreate(null).
+    } else {
+        // Else,
+        // Let options be ? ToObject(options).
+        options = optionsInput.toObject(state);
+    }
+
+    // Let opt be a new Record.
+    StringMap opt;
+    // Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
+    // Set opt.[[localeMatcher]] to matcher.
+    Value localeMatcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
+    String* matcher = localeMatcherValues[1].asString();
+    if (options) {
+        matcher = Intl::getOption(state, options.value(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, localeMatcherValues, 2, localeMatcherValues[1]).asString();
+    }
+    opt.insert(std::make_pair("matcher", matcher));
+
+    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
+    Value numberingSystem;
+    if (options) {
+        numberingSystem = Intl::getOption(state, options.value(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
+    }
+    // If numberingSystem is not undefined, then
+    if (!numberingSystem.isUndefined()) {
+        // If numberingSystem does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
+        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
+        }
+    }
+
+    // Set opt.[[nu]] to numberingSystem.
+    if (!numberingSystem.isUndefined()) {
+        opt.insert(std::make_pair("nu", numberingSystem.asString()));
+    }
+    // Let localeData be %RelativeTimeFormat%.[[LocaleData]].
+    // Let r be ResolveLocale(%RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %RelativeTimeFormat%.[[RelevantExtensionKeys]], localeData).
+    StringMap r = Intl::resolveLocale(state, state.context()->vmInstance()->intlRelativeTimeFormatAvailableLocales(), requestedLocales, opt, intlRelativeTimeFormatRelevantExtensionKeys, intlRelativeTimeFormatRelevantExtensionKeysLength, localeDataRelativeTimeFormat);
+    // Let locale be r.[[Locale]].
+    String* locale = r.at("locale");
+    // Set relativeTimeFormat.[[Locale]] to locale.
+    m_locale = locale;
+    // Set relativeTimeFormat.[[DataLocale]] to r.[[DataLocale]].
+    m_dataLocale = r.at("dataLocale");
+    // Set relativeTimeFormat.[[NumberingSystem]] to r.[[nu]].
+    m_numberingSystem = r.at("nu");
+    // Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long").
+
+    Value styleValues[3] = { state.context()->staticStrings().lazyLong().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyNarrow().string() };
+    String* style = styleValues[0].asString();
+    // Set relativeTimeFormat.[[Style]] to s.
+    if (options) {
+        style = Intl::getOption(state, options.value(), state.context()->staticStrings().lazyStyle().string(), Intl::StringValue, styleValues, 3, styleValues[0]).asString();
+    }
+    m_style = style;
+    // Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always").
+    Value numericValues[2] = { state.context()->staticStrings().lazyAlways().string(), state.context()->staticStrings().lazyAuto().string() };
+    String* numeric = numericValues[0].asString();
+    if (options) {
+        numeric = Intl::getOption(state, options.value(), state.context()->staticStrings().numeric.string(), Intl::StringValue, numericValues, 2, numericValues[0]).asString();
+    }
+    // Set relativeTimeFormat.[[Numeric]] to numeric.
+    m_numeric = numeric;
+    // Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%NumberFormat%, « locale »).
+    // Let relativeTimeFormat.[[PluralRules]] be ! Construct(%PluralRules%, « locale »).
+    // Return relativeTimeFormat.
+
+    UDateRelativeDateTimeFormatterStyle icuStyle;
+    if (m_style->equals("short")) {
+        icuStyle = UDAT_STYLE_SHORT;
+    } else if (m_style->equals("narrow")) {
+        icuStyle = UDAT_STYLE_NARROW;
+    } else {
+        ASSERT(m_style->equals("long"));
+        icuStyle = UDAT_STYLE_LONG;
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    m_icuRelativeDateTimeFormatter = ureldatefmt_open(m_locale->toNonGCUTF8StringData().data(), nullptr, icuStyle, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, &status);
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize RelativeTimeFormat");
+    }
+
+    addFinalizer([](Object* obj, void* data) {
+        IntlRelativeTimeFormatObject* self = (IntlRelativeTimeFormatObject*)obj;
+        ureldatefmt_close(self->m_icuRelativeDateTimeFormatter);
+    },
+                 nullptr);
+}
+
+static URelativeDateTimeUnit icuRelativeTimeUnitFromString(String* unit)
+{
+    if (unit->equals("seconds") || unit->equals("second")) {
+        return UDAT_REL_UNIT_SECOND;
+    } else if (unit->equals("minutes") || unit->equals("minute")) {
+        return UDAT_REL_UNIT_MINUTE;
+    } else if (unit->equals("hours") || unit->equals("hour")) {
+        return UDAT_REL_UNIT_HOUR;
+    } else if (unit->equals("days") || unit->equals("day")) {
+        return UDAT_REL_UNIT_DAY;
+    } else if (unit->equals("weeks") || unit->equals("week")) {
+        return UDAT_REL_UNIT_WEEK;
+    } else if (unit->equals("months") || unit->equals("month")) {
+        return UDAT_REL_UNIT_MONTH;
+    } else if (unit->equals("quarters") || unit->equals("quarter")) {
+        return UDAT_REL_UNIT_QUARTER;
+    } else if (unit->equals("years") || unit->equals("year")) {
+        return UDAT_REL_UNIT_YEAR;
+    } else {
+        return UDAT_REL_UNIT_COUNT;
+    }
+}
+
+String* IntlRelativeTimeFormatObject::format(ExecutionState& state, double value, String* unit)
+{
+    // https://tc39.es/ecma402/#sec-PartitionRelativeTimePattern
+    if (std::isinf(value) || std::isnan(value) || !IS_IN_TIME_RANGE(value)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "value is valid in RelativeTimeFormat format()");
+    }
+
+    // https://tc39.es/ecma402/#sec-singularrelativetimeunit
+    URelativeDateTimeUnit icuUnit = icuRelativeTimeUnitFromString(unit);
+
+    if (icuUnit == UDAT_REL_UNIT_COUNT) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is invalid in RelativeTimeFormat format()");
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t bufSize;
+    if (m_numeric->equals("always")) {
+        bufSize = ureldatefmt_formatNumeric(m_icuRelativeDateTimeFormatter, value, icuUnit, nullptr, 0, &status);
+    } else {
+        bufSize = ureldatefmt_format(m_icuRelativeDateTimeFormatter, value, icuUnit, nullptr, 0, &status);
+    }
+
+    if (status != U_BUFFER_OVERFLOW_ERROR) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    status = U_ZERO_ERROR;
+    UChar* buf = (UChar*)alloca(sizeof(UChar) * (bufSize + 1));
+    if (m_numeric->equals("always")) {
+        ureldatefmt_formatNumeric(m_icuRelativeDateTimeFormatter, value, icuUnit, buf, bufSize + 1, &status);
+    } else {
+        ureldatefmt_format(m_icuRelativeDateTimeFormatter, value, icuUnit, buf, bufSize + 1, &status);
+    }
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+    return new UTF16String(buf, bufSize);
+}
+
+ArrayObject* IntlRelativeTimeFormatObject::formatToParts(ExecutionState& state, double value, String* unit)
+{
+    // https://tc39.es/ecma402/#sec-PartitionRelativeTimePattern
+    if (std::isinf(value) || std::isnan(value) || !IS_IN_TIME_RANGE(value)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "value is valid in RelativeTimeFormat formatToParts()");
+    }
+
+    // https://tc39.es/ecma402/#sec-singularrelativetimeunit
+    URelativeDateTimeUnit icuUnit = icuRelativeTimeUnitFromString(unit);
+
+    if (icuUnit == UDAT_REL_UNIT_COUNT) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is invalid in RelativeTimeFormat formatToParts()");
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    LocalResourcePointer<UFormattedRelativeDateTime> formattedRelativeDateTime(ureldatefmt_openResult(&status), [](UFormattedRelativeDateTime* f) { ureldatefmt_closeResult(f); });
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    if (m_numeric->equals("always")) {
+        ureldatefmt_formatNumericToResult(m_icuRelativeDateTimeFormatter, value, icuUnit, formattedRelativeDateTime.get(), &status);
+    } else {
+        ureldatefmt_formatToResult(m_icuRelativeDateTimeFormatter, value, icuUnit, formattedRelativeDateTime.get(), &status);
+    }
+
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    const UFormattedValue* formattedValue = ureldatefmt_resultAsValue(formattedRelativeDateTime.get(), &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    int32_t strLength;
+    const char16_t* str = ufmtval_getString(formattedValue, &strLength, &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    UTF16StringDataNonGCStd resultString(str, strLength);
+
+    LocalResourcePointer<UConstrainedFieldPosition> fpos(ucfpos_open(&status), [](UConstrainedFieldPosition* f) { ucfpos_close(f); });
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    ucfpos_constrainCategory(fpos.get(), UFIELD_CATEGORY_NUMBER, &status);
+    if (U_FAILURE(status)) {
+        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+    }
+
+    std::vector<Intl::NumberFieldItem> fields;
+
+    while (true) {
+        bool hasNext = ufmtval_nextPosition(formattedValue, fpos.get(), &status);
+        if (U_FAILURE(status)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+        }
+        if (!hasNext) {
+            break;
+        }
+
+        int32_t type = ucfpos_getField(fpos.get(), &status);
+        if (U_FAILURE(status)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+        }
+
+        int32_t start, end;
+        ucfpos_getIndexes(fpos.get(), &start, &end, &status);
+        if (U_FAILURE(status)) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
+        }
+
+        Intl::NumberFieldItem item;
+        item.start = start;
+        item.end = end;
+        item.type = type;
+
+        fields.push_back(item);
+    }
+
+    Intl::convertICUNumberFieldToEcmaNumberField(fields, value, resultString);
+
+    if (icuUnit == UDAT_REL_UNIT_SECOND) {
+        unit = state.context()->staticStrings().lazySecond().string();
+    } else if (icuUnit == UDAT_REL_UNIT_MINUTE) {
+        unit = state.context()->staticStrings().lazyMinute().string();
+    } else if (icuUnit == UDAT_REL_UNIT_HOUR) {
+        unit = state.context()->staticStrings().lazyHour().string();
+    } else if (icuUnit == UDAT_REL_UNIT_DAY) {
+        unit = state.context()->staticStrings().lazyDay().string();
+    } else if (icuUnit == UDAT_REL_UNIT_WEEK) {
+        unit = state.context()->staticStrings().lazyWeek().string();
+    } else if (icuUnit == UDAT_REL_UNIT_MONTH) {
+        unit = state.context()->staticStrings().lazyMonth().string();
+    } else if (icuUnit == UDAT_REL_UNIT_QUARTER) {
+        unit = state.context()->staticStrings().lazyQuarter().string();
+    } else {
+        ASSERT(icuUnit == UDAT_REL_UNIT_YEAR);
+        unit = state.context()->staticStrings().lazyYear().string();
+    }
+
+    AtomicString unitAtom(state, "unit");
+    AtomicString typeAtom(state, "type");
+    AtomicString valueAtom = state.context()->staticStrings().value;
+
+    ArrayObject* result = new ArrayObject(state);
+    for (size_t i = 0; i < fields.size(); i++) {
+        const Intl::NumberFieldItem& item = fields[i];
+
+        Object* o = new Object(state);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(Intl::icuNumberFieldToString(state, item.type, value), ObjectPropertyDescriptor::AllPresent));
+        auto sub = resultString.substr(item.start, item.end - item.start);
+        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
+        if (item.type != -1) {
+            o->defineOwnPropertyThrowsException(state, ObjectPropertyName(unitAtom), ObjectPropertyDescriptor(unit, ObjectPropertyDescriptor::AllPresent));
+        }
+
+        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
+    }
+
+    return result;
+}
+
+} // namespace Escargot
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/intl/IntlRelativeTimeFormat.h
new file mode 100644 (file)
index 0000000..91dc6ec
--- /dev/null
@@ -0,0 +1,79 @@
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+/*
+ * Copyright (c) 2020-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+
+#ifndef __EscargotIntlRelativeTimeFormat__
+#define __EscargotIntlRelativeTimeFormat__
+
+#include "runtime/Object.h"
+
+namespace Escargot {
+
+class IntlRelativeTimeFormatObject : public Object {
+public:
+    IntlRelativeTimeFormatObject(ExecutionState& state, Value locales, Value options);
+    IntlRelativeTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value options);
+
+    virtual bool isIntlRelativeTimeFormatObject() const override
+    {
+        return true;
+    }
+
+    String* locale() const
+    {
+        return m_locale;
+    }
+
+    String* dataLocale() const
+    {
+        return m_dataLocale;
+    }
+
+    String* numberingSystem() const
+    {
+        return m_numberingSystem;
+    }
+
+    String* style() const
+    {
+        return m_style;
+    }
+
+    String* numeric() const
+    {
+        return m_numeric;
+    }
+
+    String* format(ExecutionState& state, double value, String* unit);
+    ArrayObject* formatToParts(ExecutionState& state, double value, String* unit);
+
+protected:
+    String* m_locale;
+    String* m_dataLocale;
+    String* m_numberingSystem;
+    String* m_style;
+    String* m_numeric;
+
+    URelativeDateTimeFormatter* m_icuRelativeDateTimeFormatter;
+};
+
+} // namespace Escargot
+#endif
+#endif
index 776af78df99819f8a05235b178b9287be358c376..2e1309120f3e87d2e51dad3481cff1f1fae50e8e 100644 (file)
 #include "interpreter/ByteCodeInterpreter.h"
 #include "parser/ast/Node.h"
 #include "runtime/Context.h"
+#include "runtime/Global.h"
 #include "runtime/Environment.h"
 #include "runtime/EnvironmentRecord.h"
+#include "runtime/Platform.h"
 #include "runtime/ErrorObject.h"
 #include "runtime/ExtendedNativeFunctionObject.h"
 #include "runtime/SandBox.h"
@@ -80,12 +82,12 @@ Context* Script::context()
 
 Script* Script::loadModuleFromScript(ExecutionState& state, String* src)
 {
-    Platform::LoadModuleResult result = context()->vmInstance()->platform()->onLoadModule(context(), this, src);
+    Platform::LoadModuleResult result = Global::platform()->onLoadModule(context(), this, src);
     if (!result.script) {
         ErrorObject::throwBuiltinError(state, (ErrorObject::Code)result.errorCode, result.errorMessage->toNonGCUTF8StringData().data());
     }
     if (!result.script->moduleData()->m_didCallLoadedCallback) {
-        context()->vmInstance()->platform()->didLoadModule(context(), this, result.script.value());
+        Global::platform()->didLoadModule(context(), this, result.script.value());
         result.script->moduleData()->m_didCallLoadedCallback = true;
     }
     return result.script.value();
@@ -323,7 +325,7 @@ Value Script::execute(ExecutionState& state, bool isExecuteOnEvalFunction, bool
 
     if (isModule()) {
         if (!moduleData()->m_didCallLoadedCallback) {
-            context()->vmInstance()->platform()->didLoadModule(context(), nullptr, this);
+            Global::platform()->didLoadModule(context(), nullptr, this);
             moduleData()->m_didCallLoadedCallback = true;
         }
 
index 22af6478690f3fded0a4fd75a7108e815b21a38f..d63fa924aa77614153518e3925123f3733a21597 100644 (file)
@@ -418,22 +418,29 @@ public:
 
         VectorWithInlineStorage<8, SyntaxNode, std::allocator<SyntaxNode>>& params = paramsResult.params;
         bool hasParameterOtherThanIdentifier = false;
+        bool seenDefaultParameter = false;
 
         for (size_t i = 0; i < params.size(); i++) {
             switch (params[i]->type()) {
-            case Identifier: {
-                if (!hasParameterOtherThanIdentifier) {
+            case Identifier:
+                if (LIKELY(!seenDefaultParameter)) {
                     this->currentScopeContext->m_functionLength++;
                 }
                 break;
-            }
             case AssignmentPattern:
+                seenDefaultParameter = true;
+                hasParameterOtherThanIdentifier = true;
+                break;
             case ArrayPattern:
             case ObjectPattern:
-            case RestElement: {
+                hasParameterOtherThanIdentifier = true;
+                if (LIKELY(!seenDefaultParameter)) {
+                    this->currentScopeContext->m_functionLength++;
+                }
+                break;
+            case RestElement:
                 hasParameterOtherThanIdentifier = true;
                 break;
-            }
             default: {
                 RELEASE_ASSERT_NOT_REACHED();
             }
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.cpp
new file mode 100644 (file)
index 0000000..3176a12
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/VMInstance.h"
+#include "runtime/BackingStore.h"
+#include "runtime/ArrayBuffer.h"
+#include "runtime/TypedArrayInlines.h"
+#include "runtime/ArrayBufferObject.h"
+#include "runtime/SharedArrayBufferObject.h"
+
+namespace Escargot {
+
+unsigned TypedArrayHelper::elementSizeTable[11] = { 1, 2, 4, 1, 2, 4, 1, 4, 8, 8, 8 };
+
+ArrayBuffer::ArrayBuffer(ExecutionState& state, Object* proto)
+    : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER)
+    , m_mayPointsSharedBackingStore(false)
+{
+}
+
+// $24.1.1.6
+Value ArrayBuffer::getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian)
+{
+    // If isLittleEndian is not present, set isLittleEndian to either true or false.
+    ASSERT(byteLength());
+    size_t elemSize = TypedArrayHelper::elementSize(type);
+    ASSERT(byteindex + elemSize <= byteLength());
+    uint8_t* rawStart = data() + byteindex;
+    if (LIKELY(isLittleEndian)) {
+        return TypedArrayHelper::rawBytesToNumber(state, type, rawStart);
+    } else {
+        uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
+        for (size_t i = 0; i < elemSize; i++) {
+            rawBytes[elemSize - i - 1] = rawStart[i];
+        }
+        return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes);
+    }
+}
+
+// $24.1.1.8
+void ArrayBuffer::setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian)
+{
+    // If isLittleEndian is not present, set isLittleEndian to either true or false.
+    ASSERT(byteLength());
+    size_t elemSize = TypedArrayHelper::elementSize(type);
+    ASSERT(byteindex + elemSize <= byteLength());
+    uint8_t* rawStart = data() + byteindex;
+    uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
+    TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes);
+    if (LIKELY(isLittleEndian)) {
+        memcpy(rawStart, rawBytes, elemSize);
+    } else {
+        for (size_t i = 0; i < elemSize; i++) {
+            rawStart[i] = rawBytes[elemSize - i - 1];
+        }
+    }
+}
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ArrayBuffer.h
new file mode 100644 (file)
index 0000000..0a7efbd
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotArrayBuffer__
+#define __EscargotArrayBuffer__
+
+#include "runtime/Context.h"
+#include "runtime/BackingStore.h"
+
+namespace Escargot {
+
+enum class TypedArrayType : unsigned {
+    Int8 = 0,
+    Int16,
+    Int32,
+    Uint8,
+    Uint16,
+    Uint32,
+    Uint8Clamped,
+    Float32,
+    Float64,
+    BigInt64,
+    BigUint64
+};
+
+class ArrayBuffer : public Object {
+    friend void initializeCustomAllocators();
+
+public:
+    static const uint64_t maxArrayBufferSize = 210000000;
+
+    explicit ArrayBuffer(ExecutionState& state, Object* proto);
+
+    virtual bool isArrayBuffer() const override
+    {
+        return true;
+    }
+
+    Optional<BackingStore*> backingStore()
+    {
+        if (m_backingStore) {
+            m_mayPointsSharedBackingStore = true;
+        }
+        return m_backingStore;
+    }
+
+    ALWAYS_INLINE uint8_t* data()
+    {
+        if (LIKELY(m_backingStore)) {
+            return reinterpret_cast<uint8_t*>(m_backingStore->data());
+        }
+        return nullptr;
+    }
+
+    ALWAYS_INLINE size_t byteLength()
+    {
+        if (LIKELY(m_backingStore)) {
+            return m_backingStore->byteLength();
+        }
+        return 0;
+    }
+
+    // $24.1.1.6
+    Value getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian = true);
+
+    // $24.1.1.8
+    void setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian = true);
+
+    ALWAYS_INLINE bool isDetachedBuffer()
+    {
+        return (data() == nullptr);
+    }
+
+    ALWAYS_INLINE void throwTypeErrorIfDetached(ExecutionState& state)
+    {
+        if (UNLIKELY(isDetachedBuffer())) {
+            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().constructor.string(), ErrorObject::Messages::GlobalObject_DetachedBuffer);
+        }
+    }
+
+    void fillData(const uint8_t* newData, size_t length)
+    {
+        ASSERT(!isDetachedBuffer());
+        memcpy(data(), newData, length);
+    }
+
+    void* operator new(size_t size) = delete;
+    void* operator new[](size_t size) = delete;
+
+protected:
+    static inline void fillGCDescriptor(GC_word* desc)
+    {
+        Object::fillGCDescriptor(desc);
+        GC_set_bit(desc, GC_WORD_OFFSET(ArrayBuffer, m_backingStore));
+    }
+
+    bool m_mayPointsSharedBackingStore;
+    Optional<BackingStore*> m_backingStore;
+};
+
+class ArrayBufferView : public Object {
+public:
+    explicit ArrayBufferView(ExecutionState& state, Object* proto)
+        : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER)
+        , m_buffer(nullptr)
+        , m_byteLength(0)
+        , m_byteOffset(0)
+        , m_arrayLength(0)
+    {
+    }
+
+    ALWAYS_INLINE ArrayBuffer* buffer() { return m_buffer; }
+    ALWAYS_INLINE size_t byteLength() { return m_byteLength; }
+    ALWAYS_INLINE size_t byteOffset() { return m_byteOffset; }
+    ALWAYS_INLINE size_t arrayLength() { return m_arrayLength; }
+    ALWAYS_INLINE uint8_t* rawBuffer()
+    {
+        return m_buffer ? (uint8_t*)(m_buffer->data() + m_byteOffset) : nullptr;
+    }
+
+    ALWAYS_INLINE void setBuffer(ArrayBuffer* bo, size_t byteOffset, size_t byteLength, size_t arrayLength)
+    {
+        m_buffer = bo;
+        m_byteOffset = byteOffset;
+        m_byteLength = byteLength;
+        m_arrayLength = arrayLength;
+    }
+
+    ALWAYS_INLINE void setBuffer(ArrayBuffer* bo, size_t byteOffset, size_t byteLength)
+    {
+        m_buffer = bo;
+        m_byteOffset = byteOffset;
+        m_byteLength = byteLength;
+    }
+
+    virtual bool isArrayBufferView() const override
+    {
+        return true;
+    }
+
+    void* operator new(size_t size)
+    {
+        static MAY_THREAD_LOCAL bool typeInited = false;
+        static MAY_THREAD_LOCAL GC_descr descr;
+        if (!typeInited) {
+            GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferView)] = { 0 };
+            Object::fillGCDescriptor(obj_bitmap);
+            GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferView, m_buffer));
+            descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferView));
+            typeInited = true;
+        }
+        return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
+    }
+    void* operator new[](size_t size) = delete;
+
+private:
+    ArrayBuffer* m_buffer;
+    size_t m_byteLength;
+    size_t m_byteOffset;
+    size_t m_arrayLength;
+};
+
+} // namespace Escargot
+
+#endif
index fceceefccb9c58a24fd89946f2d532a8897ba225..f0ff07f88dfa0d70071580e3f13a89fca9ba293f 100644 (file)
@@ -25,8 +25,6 @@
 
 namespace Escargot {
 
-unsigned TypedArrayHelper::elementSizeTable[11] = { 1, 2, 4, 1, 2, 4, 1, 4, 8, 8, 8 };
-
 ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength)
 {
     // https://www.ecma-international.org/ecma-262/10.0/#sec-allocatearraybuffer
@@ -34,7 +32,7 @@ ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state,
         return constructorRealm->globalObject()->arrayBufferPrototype();
     });
 
-    if (byteLength >= ArrayBufferObject::maxArrayBufferSize) {
+    if (byteLength >= ArrayBuffer::maxArrayBufferSize) {
         ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize);
     }
 
@@ -44,7 +42,7 @@ ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state,
     return obj;
 }
 
-ArrayBufferObject* ArrayBufferObject::cloneArrayBuffer(ExecutionState& state, ArrayBufferObject* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor)
+ArrayBufferObject* ArrayBufferObject::cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor)
 {
     // https://www.ecma-international.org/ecma-262/10.0/#sec-clonearraybuffer
     ASSERT(constructor->isConstructor());
@@ -63,8 +61,7 @@ ArrayBufferObject::ArrayBufferObject(ExecutionState& state)
 }
 
 ArrayBufferObject::ArrayBufferObject(ExecutionState& state, Object* proto)
-    : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER)
-    , m_mayPointsSharedBackingStore(false)
+    : ArrayBuffer(state, proto)
 {
 }
 
@@ -72,7 +69,7 @@ void ArrayBufferObject::allocateBuffer(ExecutionState& state, size_t byteLength)
 {
     detachArrayBuffer();
 
-    ASSERT(byteLength < ArrayBufferObject::maxArrayBufferSize);
+    ASSERT(byteLength < ArrayBuffer::maxArrayBufferSize);
 
     const size_t ratio = std::max((size_t)GC_get_free_space_divisor() / 6, (size_t)1);
     if (byteLength > (GC_get_heap_size() / ratio)) {
@@ -85,7 +82,7 @@ void ArrayBufferObject::allocateBuffer(ExecutionState& state, size_t byteLength)
         GC_invoke_finalizers();
     }
 
-    m_backingStore = new BackingStore(state.context()->vmInstance(), byteLength);
+    m_backingStore = new BackingStore(byteLength);
 }
 
 void ArrayBufferObject::attachBuffer(BackingStore* backingStore)
@@ -105,7 +102,7 @@ void ArrayBufferObject::detachArrayBuffer()
 
     if (m_backingStore && !m_mayPointsSharedBackingStore) {
         // if backingstore is definitely not shared, we deallocate the backingstore immediately.
-        m_backingStore.value()->deallocate();
+        delete m_backingStore.value();
     }
     m_backingStore.reset();
     m_mayPointsSharedBackingStore = false;
@@ -118,8 +115,7 @@ void* ArrayBufferObject::operator new(size_t size)
     static MAY_THREAD_LOCAL GC_descr descr;
     if (!typeInited) {
         GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferObject)] = { 0 };
-        Object::fillGCDescriptor(obj_bitmap);
-        GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferObject, m_backingStore));
+        ArrayBuffer::fillGCDescriptor(obj_bitmap);
         descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferObject));
         typeInited = true;
     }
@@ -128,42 +124,4 @@ void* ArrayBufferObject::operator new(size_t size)
     return CustomAllocator<ArrayBufferObject>().allocate(1);
 #endif
 }
-
-// $24.1.1.6
-Value ArrayBufferObject::getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian)
-{
-    // If isLittleEndian is not present, set isLittleEndian to either true or false.
-    ASSERT(byteLength());
-    size_t elemSize = TypedArrayHelper::elementSize(type);
-    ASSERT(byteindex + elemSize <= byteLength());
-    uint8_t* rawStart = data() + byteindex;
-    if (LIKELY(isLittleEndian)) {
-        return TypedArrayHelper::rawBytesToNumber(state, type, rawStart);
-    } else {
-        uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
-        for (size_t i = 0; i < elemSize; i++) {
-            rawBytes[elemSize - i - 1] = rawStart[i];
-        }
-        return TypedArrayHelper::rawBytesToNumber(state, type, rawBytes);
-    }
-}
-
-// $24.1.1.8
-void ArrayBufferObject::setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian)
-{
-    // If isLittleEndian is not present, set isLittleEndian to either true or false.
-    ASSERT(byteLength());
-    size_t elemSize = TypedArrayHelper::elementSize(type);
-    ASSERT(byteindex + elemSize <= byteLength());
-    uint8_t* rawStart = data() + byteindex;
-    uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
-    TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes);
-    if (LIKELY(isLittleEndian)) {
-        memcpy(rawStart, rawBytes, elemSize);
-    } else {
-        for (size_t i = 0; i < elemSize; i++) {
-            rawStart[i] = rawBytes[elemSize - i - 1];
-        }
-    }
-}
 } // namespace Escargot
index 3f7fb7f9a6f15b7d31cf2a1eb05801927d92f049..54d12029dfad36a289ff0dbcf265ed8d356bbb17 100644 (file)
 #ifndef __EscargotArrayBufferObject__
 #define __EscargotArrayBufferObject__
 
-#include "runtime/Context.h"
-#include "runtime/BackingStore.h"
+#include "runtime/ArrayBuffer.h"
 
 namespace Escargot {
 
-enum class TypedArrayType : unsigned {
-    Int8 = 0,
-    Int16,
-    Int32,
-    Uint8,
-    Uint16,
-    Uint32,
-    Uint8Clamped,
-    Float32,
-    Float64,
-    BigInt64,
-    BigUint64
-};
-
-class ArrayBufferObject : public Object {
+class ArrayBufferObject : public ArrayBuffer {
     friend void initializeCustomAllocators();
     friend int getValidValueInArrayBufferObject(void* ptr, GC_mark_custom_result* arr);
 
@@ -48,132 +33,21 @@ public:
     explicit ArrayBufferObject(ExecutionState& state, Object* proto);
 
     static ArrayBufferObject* allocateArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength);
-    static ArrayBufferObject* cloneArrayBuffer(ExecutionState& state, ArrayBufferObject* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor);
-
-    static const uint64_t maxArrayBufferSize = 210000000;
+    static ArrayBufferObject* cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor);
 
     void allocateBuffer(ExecutionState& state, size_t bytelength);
     void attachBuffer(BackingStore* backingStore);
     void detachArrayBuffer();
-    Optional<BackingStore*> backingStore()
-    {
-        if (m_backingStore) {
-            m_mayPointsSharedBackingStore = true;
-        }
-        return m_backingStore;
-    }
 
     virtual bool isArrayBufferObject() const
     {
         return true;
     }
 
-    ALWAYS_INLINE uint8_t* data()
-    {
-        if (LIKELY(m_backingStore)) {
-            return reinterpret_cast<uint8_t*>(m_backingStore->data());
-        }
-        return nullptr;
-    }
-    ALWAYS_INLINE size_t byteLength()
-    {
-        if (LIKELY(m_backingStore)) {
-            return m_backingStore->byteLength();
-        }
-        return 0;
-    }
-    // $24.1.1.6
-    Value getValueFromBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, bool isLittleEndian = true);
-    // $24.1.1.8
-    void setValueInBuffer(ExecutionState& state, size_t byteindex, TypedArrayType type, const Value& val, bool isLittleEndian = true);
-
-    ALWAYS_INLINE bool isDetachedBuffer()
-    {
-        return (data() == nullptr);
-    }
-
-    ALWAYS_INLINE void throwTypeErrorIfDetached(ExecutionState& state)
-    {
-        if (UNLIKELY(isDetachedBuffer())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().constructor.string(), ErrorObject::Messages::GlobalObject_DetachedBuffer);
-        }
-    }
-
-    void fillData(const uint8_t* newData, size_t length)
-    {
-        ASSERT(!isDetachedBuffer());
-        memcpy(data(), newData, length);
-    }
-
     void* operator new(size_t size);
     void* operator new[](size_t size) = delete;
-
-protected:
-    bool m_mayPointsSharedBackingStore;
-    Optional<BackingStore*> m_backingStore;
 };
 
-class ArrayBufferView : public Object {
-public:
-    explicit ArrayBufferView(ExecutionState& state, Object* proto)
-        : Object(state, proto, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER)
-        , m_buffer(nullptr)
-        , m_byteLength(0)
-        , m_byteOffset(0)
-        , m_arrayLength(0)
-    {
-    }
-
-    ALWAYS_INLINE ArrayBufferObject* buffer() { return m_buffer; }
-    ALWAYS_INLINE size_t byteLength() { return m_byteLength; }
-    ALWAYS_INLINE size_t byteOffset() { return m_byteOffset; }
-    ALWAYS_INLINE size_t arrayLength() { return m_arrayLength; }
-    ALWAYS_INLINE uint8_t* rawBuffer()
-    {
-        return m_buffer ? (uint8_t*)(m_buffer->data() + m_byteOffset) : nullptr;
-    }
-
-    ALWAYS_INLINE void setBuffer(ArrayBufferObject* bo, size_t byteOffset, size_t byteLength, size_t arrayLength)
-    {
-        m_buffer = bo;
-        m_byteOffset = byteOffset;
-        m_byteLength = byteLength;
-        m_arrayLength = arrayLength;
-    }
-
-    ALWAYS_INLINE void setBuffer(ArrayBufferObject* bo, size_t byteOffset, size_t byteLength)
-    {
-        m_buffer = bo;
-        m_byteOffset = byteOffset;
-        m_byteLength = byteLength;
-    }
-
-    virtual bool isArrayBufferView() const override
-    {
-        return true;
-    }
-
-    void* operator new(size_t size)
-    {
-        static MAY_THREAD_LOCAL bool typeInited = false;
-        static MAY_THREAD_LOCAL GC_descr descr;
-        if (!typeInited) {
-            GC_word obj_bitmap[GC_BITMAP_SIZE(ArrayBufferView)] = { 0 };
-            Object::fillGCDescriptor(obj_bitmap);
-            GC_set_bit(obj_bitmap, GC_WORD_OFFSET(ArrayBufferView, m_buffer));
-            descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(ArrayBufferView));
-            typeInited = true;
-        }
-        return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
-    }
-    void* operator new[](size_t size) = delete;
-
-private:
-    ArrayBufferObject* m_buffer;
-    size_t m_byteLength;
-    size_t m_byteOffset;
-    size_t m_arrayLength;
-};
 } // namespace Escargot
 
 #endif
index d9e5981b089a1848d5c82971e23aa0322a548cc8..bd1c87527d431d110bdeb3d1ec50f7d26b4ebf20 100644 (file)
@@ -33,6 +33,7 @@ class ArrayIteratorObject;
 
 class ArrayObject : public Object {
     friend class VMInstance;
+    friend class Global;
     friend class ByteCodeInterpreter;
     friend class EnumerateObjectWithDestruction;
     friend class EnumerateObjectWithIteration;
@@ -97,7 +98,7 @@ protected:
 #endif
     {
         // dummy default constructor
-        // only called by VMInstance::initialize to set tag value
+        // only called by Global::initialize to set tag value
     }
 
 private:
@@ -141,7 +142,7 @@ private:
 };
 
 class ArrayPrototypeObject : public ArrayObject {
-    friend class VMInstance;
+    friend class Global;
 
 public:
     explicit ArrayPrototypeObject(ExecutionState& state);
@@ -151,7 +152,7 @@ private:
         : ArrayObject()
     {
         // dummy default constructor
-        // only called by VMInstance::initialize to set tag value
+        // only called by Global::initialize to set tag value
     }
 };
 
index 6b512d1a3512ab64a90a2ba41602d8b738531110..7adaefa659b2b6ed95fc9b711e428951e1737f0b 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "Escargot.h"
 #include "BackingStore.h"
-#include "runtime/VMInstance.h"
+#include "runtime/Global.h"
 #include "runtime/Platform.h"
 
 namespace Escargot {
@@ -40,18 +40,28 @@ void* BackingStore::operator new(size_t size)
 
 static void defaultPlatformBackingStoreDeleter(void* data, size_t length, void* deleterData)
 {
-    if (deleterData) {
-        VMInstance* instance = (VMInstance*)deleterData;
-        instance->platform()->onFreeArrayBufferObjectDataBuffer(data, length);
-    } else {
-        ASSERT(data == nullptr);
+    if (!!data) {
+        Global::platform()->onFreeArrayBufferObjectDataBuffer(data, length);
     }
 }
 
+BackingStore::~BackingStore()
+{
+    // Shared Data Block should not be deleted explicitly
+    ASSERT(!m_isShared);
+    m_deleter(m_data, m_byteLength, m_deleterData);
+    GC_REGISTER_FINALIZER_NO_ORDER(this, nullptr, nullptr, nullptr, nullptr);
+    m_data = nullptr;
+    m_byteLength = 0;
+    m_deleter = defaultPlatformBackingStoreDeleter;
+    m_deleterData = nullptr;
+    m_isAllocatedByPlatformAllocator = true;
+}
+
 BackingStore::BackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData,
-                           bool isShared, bool isAllocatedByPlatformAllocator)
+                           bool isShared)
     : m_isShared(isShared)
-    , m_isAllocatedByPlatformAllocator(isAllocatedByPlatformAllocator)
+    , m_isAllocatedByPlatformAllocator(false)
     , m_data(data)
     , m_byteLength(byteLength)
     , m_deleter(callback)
@@ -64,13 +74,14 @@ BackingStore::BackingStore(void* data, size_t byteLength, BackingStoreDeleterCal
                                    nullptr, nullptr, nullptr);
 }
 
-BackingStore::BackingStore(VMInstance* instance, size_t byteLength)
-    : BackingStore(instance->platform()->onMallocArrayBufferObjectDataBuffer(byteLength), byteLength,
-                   defaultPlatformBackingStoreDeleter, instance, false, true)
+BackingStore::BackingStore(size_t byteLength)
+    : BackingStore(Global::platform()->onMallocArrayBufferObjectDataBuffer(byteLength), byteLength,
+                   defaultPlatformBackingStoreDeleter, nullptr, false)
 {
+    m_isAllocatedByPlatformAllocator = true;
 }
 
-void BackingStore::reallocate(VMInstance* instance, size_t newByteLength)
+void BackingStore::reallocate(size_t newByteLength)
 {
     // Shared Data Block should not be reallocated
     ASSERT(!m_isShared);
@@ -80,29 +91,16 @@ void BackingStore::reallocate(VMInstance* instance, size_t newByteLength)
     }
 
     if (m_isAllocatedByPlatformAllocator) {
-        m_data = instance->platform()->onReallocArrayBufferObjectDataBuffer(m_data, m_byteLength, newByteLength);
+        m_data = Global::platform()->onReallocArrayBufferObjectDataBuffer(m_data, m_byteLength, newByteLength);
         m_byteLength = newByteLength;
     } else {
         m_deleter(m_data, m_byteLength, m_deleterData);
-        m_data = instance->platform()->onMallocArrayBufferObjectDataBuffer(newByteLength);
+        m_data = Global::platform()->onMallocArrayBufferObjectDataBuffer(newByteLength);
         m_deleter = defaultPlatformBackingStoreDeleter;
-        m_deleterData = instance;
+        m_deleterData = nullptr;
         m_byteLength = newByteLength;
         m_isAllocatedByPlatformAllocator = true;
     }
 }
 
-void BackingStore::deallocate()
-{
-    // Shared Data Block should not be deleted explicitly
-    ASSERT(!m_isShared);
-    m_deleter(m_data, m_byteLength, m_deleterData);
-    GC_REGISTER_FINALIZER_NO_ORDER(this, nullptr, nullptr, nullptr, nullptr);
-    m_data = nullptr;
-    m_byteLength = 0;
-    m_deleter = defaultPlatformBackingStoreDeleter;
-    m_deleterData = nullptr;
-    m_isAllocatedByPlatformAllocator = true;
-}
-
 } // namespace Escargot
index 272e2a3cb21c5849228b68f07b3fad38a0bc6355..fd068fae87dcf139aa935ac9e01a0b05cc8bb78a 100644 (file)
@@ -22,8 +22,6 @@
 
 namespace Escargot {
 
-class VMInstance;
-
 using BackingStoreDeleterCallback = void (*)(void* data, size_t length,
                                              void* deleterData);
 
@@ -31,9 +29,10 @@ class BackingStore : public gc {
     friend class ArrayBufferObject;
 
 public:
-    BackingStore(VMInstance* instance, size_t byteLength);
+    BackingStore(size_t byteLength);
     BackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback,
-                 void* callbackData, bool isShared = false, bool isAllocatedByPlatformAllocator = false);
+                 void* callbackData, bool isShared = false);
+    ~BackingStore();
 
     void* data() const
     {
@@ -50,14 +49,18 @@ public:
         return m_isShared;
     }
 
-    void reallocate(VMInstance* instance, size_t newByteLength);
-    void deallocate();
+    void* deleterData() const
+    {
+        return m_deleterData;
+    }
+
+    void reallocate(size_t newByteLength);
 
     void* operator new(size_t size);
     void* operator new[](size_t size) = delete;
 
 private:
-    // Indicates whether the backing store was created as Shared Data Block
+    // Indicates whether the backing store was created for SharedArrayBuffer
     bool m_isShared;
     bool m_isAllocatedByPlatformAllocator;
     void* m_data;
index 6a01947b5b645766a0cf48e85ce944ed3d6556ec..0cf3305717921884cde6feb97d1dfccd23228e2d 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "Escargot.h"
 #include "BigInt.h"
-#include "VMInstance.h"
+#include "ThreadLocal.h"
 #include "ErrorObject.h"
 
 namespace Escargot {
@@ -38,7 +38,7 @@ BigIntData::BigIntData(BigIntData&& src)
 
 BigIntData::BigIntData(const double& d)
 {
-    bf_init(VMInstance::bfContext(), &m_data);
+    bf_init(ThreadLocal::bfContext(), &m_data);
     bf_set_float64(&m_data, d);
 }
 
@@ -51,7 +51,7 @@ BigIntData::BigIntData(String* src)
         buffer = (char*)bd.bufferAs8Bit;
     } else {
         if (!isAllASCII(bd.bufferAs16Bit, bd.length)) {
-            bf_init(VMInstance::bfContext(), &m_data);
+            bf_init(ThreadLocal::bfContext(), &m_data);
             bf_set_nan(&m_data);
             return;
         }
@@ -72,7 +72,7 @@ BigIntData::BigIntData(const char* buf, size_t length, int radix)
 
 void BigIntData::init(const char* buf, size_t length, int radix)
 {
-    bf_init(VMInstance::bfContext(), &m_data);
+    bf_init(ThreadLocal::bfContext(), &m_data);
     if (!length) {
         bf_set_zero(&m_data, 0);
         return;
@@ -155,7 +155,7 @@ void BigInt::initFinalizer()
 BigInt::BigInt()
     : m_tag(POINTER_VALUE_BIGINT_TAG_IN_DATA)
 {
-    bf_init(VMInstance::bfContext(), &m_bf);
+    bf_init(ThreadLocal::bfContext(), &m_bf);
     initFinalizer();
 }
 
@@ -266,7 +266,7 @@ String* BigInt::toString(int radix)
         return String::emptyString;
     } else {
         String* ret = String::fromASCII(str, resultLen);
-        bf_free(VMInstance::bfContext(), str);
+        bf_free(ThreadLocal::bfContext(), str);
         return ret;
     }
 }
@@ -358,7 +358,7 @@ bool BigInt::greaterThanEqual(BigInt* b)
 BigInt* BigInt::addition(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_add(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -370,7 +370,7 @@ BigInt* BigInt::addition(ExecutionState& state, BigInt* b)
 BigInt* BigInt::subtraction(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_sub(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -382,7 +382,7 @@ BigInt* BigInt::subtraction(ExecutionState& state, BigInt* b)
 BigInt* BigInt::multiply(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_mul(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -394,8 +394,8 @@ BigInt* BigInt::multiply(ExecutionState& state, BigInt* b)
 BigInt* BigInt::division(ExecutionState& state, BigInt* b)
 {
     bf_t r, rem;
-    bf_init(VMInstance::bfContext(), &r);
-    bf_init(VMInstance::bfContext(), &rem);
+    bf_init(ThreadLocal::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &rem);
     int ret = bf_divrem(&r, &rem, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ,
                         BF_RNDZ);
     bf_delete(&rem);
@@ -409,7 +409,7 @@ BigInt* BigInt::division(ExecutionState& state, BigInt* b)
 BigInt* BigInt::remainder(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_rem(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ,
                      BF_RNDZ)
         & BF_ST_INVALID_OP;
@@ -423,7 +423,7 @@ BigInt* BigInt::remainder(ExecutionState& state, BigInt* b)
 BigInt* BigInt::pow(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_pow(&r, &m_bf, &b->m_bf, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -435,7 +435,7 @@ BigInt* BigInt::pow(ExecutionState& state, BigInt* b)
 BigInt* BigInt::bitwiseAnd(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_logic_and(&r, &m_bf, &b->m_bf);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -447,7 +447,7 @@ BigInt* BigInt::bitwiseAnd(ExecutionState& state, BigInt* b)
 BigInt* BigInt::bitwiseOr(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_logic_or(&r, &m_bf, &b->m_bf);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -459,7 +459,7 @@ BigInt* BigInt::bitwiseOr(ExecutionState& state, BigInt* b)
 BigInt* BigInt::bitwiseXor(ExecutionState& state, BigInt* b)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_logic_xor(&r, &m_bf, &b->m_bf);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -471,7 +471,7 @@ BigInt* BigInt::bitwiseXor(ExecutionState& state, BigInt* b)
 BigInt* BigInt::leftShift(ExecutionState& state, BigInt* src)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
 
     slimb_t v2;
 #if defined(ESCARGOT_32)
@@ -501,7 +501,7 @@ BigInt* BigInt::leftShift(ExecutionState& state, BigInt* src)
 BigInt* BigInt::rightShift(ExecutionState& state, BigInt* src)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
 
     slimb_t v2;
 #if defined(ESCARGOT_32)
@@ -534,7 +534,7 @@ BigInt* BigInt::rightShift(ExecutionState& state, BigInt* src)
 BigInt* BigInt::increment(ExecutionState& state)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_add_si(&r, &m_bf, 1, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -546,7 +546,7 @@ BigInt* BigInt::increment(ExecutionState& state)
 BigInt* BigInt::decrement(ExecutionState& state)
 {
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_add_si(&r, &m_bf, -1, BF_PREC_INF, BF_RNDZ);
     if (UNLIKELY(ret)) {
         bf_delete(&r);
@@ -559,7 +559,7 @@ BigInt* BigInt::bitwiseNot(ExecutionState& state)
 {
     // The abstract operation BigInt::bitwiseNOT with an argument x of BigInt type returns the one's complement of x; that is, -x - 1.
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_add_si(&r, &m_bf, 1, BF_PREC_INF, BF_RNDZ);
     bf_neg(&r);
 
@@ -577,7 +577,7 @@ BigInt* BigInt::negativeValue(ExecutionState& state)
     }
 
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_set(&r, &m_bf);
     bf_neg(&r);
     if (UNLIKELY(ret)) {
@@ -596,7 +596,7 @@ BigInt* BigInt::negativeValue()
     }
 
     bf_t r;
-    bf_init(VMInstance::bfContext(), &r);
+    bf_init(ThreadLocal::bfContext(), &r);
     int ret = bf_set(&r, &m_bf);
     bf_neg(&r);
     ASSERT(!ret);
index 6b69ff002bcac5bc50dcc1189589ee821ff1c7e2..efc877acdb199f40b912b86b8ddd7cc8bd46e99e 100644 (file)
@@ -20,6 +20,7 @@
 #include "Escargot.h"
 #include "Context.h"
 #include "runtime/AtomicString.h"
+#include "runtime/ThreadLocal.h"
 #include "VMInstance.h"
 #include "GlobalObject.h"
 #include "StringObject.h"
@@ -119,7 +120,7 @@ void Context::setGlobalObjectProxy(Object* newGlobalObjectProxy)
 
 ASTAllocator& Context::astAllocator()
 {
-    return *VMInstance::astAllocator();
+    return *ThreadLocal::astAllocator();
 }
 
 #ifdef ESCARGOT_DEBUGGER
index 1d78c531c02bc11385ed251f0c87f0846b10f8fd..f989e31ddd98ac4b7f2531a01ee2f53a19cfefe7 100644 (file)
@@ -53,7 +53,7 @@ public:
         }
 
         bool isLittleEndian = _isLittleEndian.toBoolean(state);
-        ArrayBufferObject* buffer = this->buffer();
+        ArrayBuffer* buffer = this->buffer();
         buffer->throwTypeErrorIfDetached(state);
 
         size_t viewOffset = byteOffset();
@@ -80,7 +80,7 @@ public:
         UNUSED_VARIABLE(numericValue);
 
         bool isLittleEndian = _isLittleEndian.toBoolean(state);
-        ArrayBufferObject* buffer = this->buffer();
+        ArrayBuffer* buffer = this->buffer();
         buffer->throwTypeErrorIfDetached(state);
 
         size_t viewOffset = byteOffset();
index 9e02cf03bd1ebe076c5886ba56727cad35d7656e..c1d5a6ff1d64cb98004add6accd6b7a8b45240af 100644 (file)
@@ -127,10 +127,16 @@ void FunctionTemplate::updateCallbackFunction(FunctionTemplateRef::NativeFunctio
 
 void FunctionTemplate::setName(AtomicString name)
 {
-    ASSERT(m_cachedObjectStructure == nullptr);
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
     m_name = name;
 }
 
+void FunctionTemplate::setLength(size_t length)
+{
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
+    m_argumentCount = length;
+}
+
 Object* FunctionTemplate::instantiate(Context* ctx)
 {
     auto& instantiatedFunctionObjects = ctx->instantiatedFunctionObjects();
@@ -141,7 +147,7 @@ Object* FunctionTemplate::instantiate(Context* ctx)
     }
 
     const size_t functionDefaultPropertyCount = m_isConstructor ? ctx->defaultStructureForFunctionObject()->propertyCount() : ctx->defaultStructureForNotConstructorFunctionObject()->propertyCount();
-    if (!m_cachedObjectStructure) {
+    if (!m_cachedObjectStructure.m_objectStructure) {
         if (m_isConstructor) {
             // [prototype, name, length]
             ASSERT(functionDefaultPropertyCount == 3);
@@ -195,7 +201,8 @@ Object* FunctionTemplate::instantiate(Context* ctx)
     flags |= m_isStrict ? NativeFunctionInfo::Strict : 0;
     flags |= m_isConstructor ? NativeFunctionInfo::Constructor : 0;
 
-    FunctionTemplateNativeFunctionObject* result = new FunctionTemplateNativeFunctionObject(ctx, m_cachedObjectStructure, std::move(objectPropertyValues), NativeFunctionInfo(m_name, m_nativeFunctionData->m_nativeFunction, m_argumentCount, flags));
+    FunctionTemplateNativeFunctionObject* result = new FunctionTemplateNativeFunctionObject(ctx,
+                                                                                            m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), NativeFunctionInfo(m_name, m_nativeFunctionData->m_nativeFunction, m_argumentCount, flags));
     result->setInternalSlotAsPointer(FunctionTemplate::BuiltinFunctionSlot::CallTemplateFunctionDataIndex, m_nativeFunctionData);
 
     if (m_isConstructor) {
index 501aa5e7b3cf41d567da72bc6b5074140f5ea3b2..81ba50c13513c945d7be470b4d08d3eac16bcefd 100644 (file)
@@ -55,7 +55,7 @@ public:
 
     void inherit(Optional<FunctionTemplate*> parent)
     {
-        ASSERT(!m_cachedObjectStructure);
+        ASSERT(!m_cachedObjectStructure.m_objectStructure);
         ASSERT(parent->m_isConstructor);
         m_parent = parent;
     }
@@ -75,7 +75,9 @@ public:
         return m_isConstructor;
     }
 
+    // setName and setLength should be called before instantiate
     void setName(AtomicString name);
+    void setLength(size_t length);
 
     void* operator new(size_t size);
     void* operator new[](size_t size) = delete;
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.cpp
new file mode 100644 (file)
index 0000000..489961a
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/Global.h"
+#include "runtime/Platform.h"
+#include "runtime/PointerValue.h"
+#include "runtime/ArrayObject.h"
+
+namespace Escargot {
+
+bool Global::inited;
+Platform* Global::g_platform;
+#if defined(ENABLE_ATOMICS_GLOBAL_LOCK)
+SpinLock Global::g_atomicsLock;
+#endif
+
+void Global::initialize(Platform* platform)
+{
+    // initialize should be invoked only once in the program
+    static bool called_once = true;
+    RELEASE_ASSERT(called_once && !inited);
+
+    ASSERT(!g_platform);
+    g_platform = platform;
+
+    // initialize PointerValue tag values
+    // tag values should be initialized once and not changed
+    PointerValue::g_arrayObjectTag = ArrayObject().getTag();
+    PointerValue::g_arrayPrototypeObjectTag = ArrayPrototypeObject().getTag();
+    PointerValue::g_objectRareDataTag = ObjectRareData(nullptr).getTag();
+    PointerValue::g_doubleInEncodedValueTag = DoubleInEncodedValue(0).getTag();
+
+    called_once = false;
+    inited = true;
+}
+
+void Global::finalize()
+{
+    // finalize should be invoked only once in the program
+    static bool called_once = true;
+    RELEASE_ASSERT(called_once && inited);
+
+    delete g_platform;
+    g_platform = nullptr;
+
+    called_once = false;
+    inited = false;
+}
+
+Platform* Global::platform()
+{
+    ASSERT(inited && !!g_platform);
+    return g_platform;
+}
+
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Global.h
new file mode 100644 (file)
index 0000000..38cdd49
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotGlobal__
+#define __EscargotGlobal__
+
+#if defined(ENABLE_THREADING) && !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+#define ENABLE_ATOMICS_GLOBAL_LOCK
+#endif
+
+#if defined(ENABLE_ATOMICS_GLOBAL_LOCK)
+#include "util/SpinLock.h"
+#endif
+
+namespace Escargot {
+
+class Platform;
+
+// Global is a global interface used by all threads
+class Global {
+    static bool inited;
+    static Platform* g_platform;
+#if defined(ENABLE_ATOMICS_GLOBAL_LOCK)
+    static SpinLock g_atomicsLock;
+#endif
+public:
+    static void initialize(Platform* platform);
+    static void finalize();
+
+    static Platform* platform();
+#if defined(ENABLE_ATOMICS_GLOBAL_LOCK)
+    static SpinLock& atomicsLock()
+    {
+        return g_atomicsLock;
+    }
+#endif
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArray.cpp
deleted file mode 100644 (file)
index 0a78647..0000000
+++ /dev/null
@@ -1,1996 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "ArrayObject.h"
-#include "IteratorObject.h"
-#include "interpreter/ByteCodeInterpreter.h"
-#include "ToStringRecursionPreventer.h"
-#include "ErrorObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-Value builtinArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    bool interpretArgumentsAsElements = false;
-    uint64_t size = 0;
-    if (argc > 1) {
-        size = argc;
-        interpretArgumentsAsElements = true;
-    } else if (argc == 1) {
-        Value& val = argv[0];
-        if (val.isNumber()) {
-            if (val.equalsTo(state, Value(val.toUint32(state)))) {
-                size = val.toNumber(state);
-            } else {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::GlobalObject_InvalidArrayLength);
-            }
-        } else {
-            size = 1;
-            interpretArgumentsAsElements = true;
-        }
-    }
-
-    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-
-    // Let proto be ? GetPrototypeFromConstructor(newTarget, "%ArrayPrototype%").
-    // Let array be ! ArrayCreate(0, proto).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->arrayPrototype();
-    });
-    ArrayObject* array = new ArrayObject(state, proto, size);
-
-    if (interpretArgumentsAsElements) {
-        Value val = argv[0];
-        if (argc > 1 || !val.isInt32()) {
-            if (array->isFastModeArray()) {
-                for (size_t idx = 0; idx < argc; idx++) {
-                    array->m_fastModeData[idx] = argv[idx];
-                }
-            } else {
-                for (size_t idx = 0; idx < argc; idx++) {
-                    array->ArrayObject::defineOwnProperty(state, ObjectPropertyName(state, idx), ObjectPropertyDescriptor(val, ObjectPropertyDescriptor::AllPresent));
-                    val = argv[idx + 1];
-                }
-            }
-        }
-    }
-    return array;
-}
-
-#define CHECK_ARRAY_LENGTH(COND)                                                                                               \
-    if (COND) {                                                                                                                \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_InvalidArrayLength); \
-    }
-
-static Object* arraySpeciesCreate(ExecutionState& state, Object* originalArray, const int64_t length)
-{
-    ASSERT(originalArray != nullptr);
-    // Assert: length is an integer Number >= 0.
-    ASSERT(length >= 0);
-
-    // Let C be undefined.
-    Value C;
-    // Let isArray be IsArray(originalArray).
-    // If isArray is true, then
-    if (originalArray->isArray(state)) {
-        // Let C be Get(originalArray, "constructor").
-        C = originalArray->get(state, ObjectPropertyName(state.context()->staticStrings().constructor)).value(state, originalArray);
-
-        // If IsConstructor(C) is true, then
-        if (C.isConstructor()) {
-            // Let thisRealm be the running execution context’s Realm.
-            Context* thisRealm = state.context();
-            // Let realmC be GetFunctionRealm(C).
-            Context* realmC = C.asObject()->getFunctionRealm(state);
-
-            // ReturnIfAbrupt(realmC).
-            // If thisRealm and realmC are not the same Realm Record, then
-            // If SameValue(C, realmC.[[intrinsics]].[[%Array%]]) is true, let C be undefined.
-            if (thisRealm != realmC) {
-                if (C.asPointerValue() == realmC->globalObject()->array()) {
-                    C = Value();
-                }
-            }
-        }
-        // If Type(C) is Object, then
-        if (C.isObject()) {
-            // a. Set C be Get(C, @@species).
-            C = C.asObject()->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species)).value(state, C);
-            if (C.isNull()) { // b. If C is null, set C to undefined.
-                C = Value();
-            }
-        }
-    }
-
-    // If C is undefined, return ArrayCreate(length).
-    if (C.isUndefined()) {
-        return new ArrayObject(state, static_cast<uint64_t>(length));
-    }
-    // If IsConstructor(C) is false, throw a TypeError exception.
-    if (!C.isConstructor()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
-    }
-    // Return Construct(C, <<length>>).
-    Value argv[1] = { Value(length) };
-    return Object::construct(state, C, 1, argv).toObject(state);
-}
-
-// http://ecma-international.org/ecma-262/10.0/#sec-flattenintoarray
-// FlattenIntoArray(target, source, sourceLen, start, depth [ , mapperFunction, thisArg ])
-static int64_t flattenIntoArray(ExecutionState& state, Value target, Value source, int64_t sourceLen, int64_t start, double depth, Value mappedValue = Value(Value::EmptyValue), Value thisArg = Value(Value::EmptyValue))
-{
-    ASSERT(target.isObject());
-    ASSERT(source.isObject());
-    ASSERT(sourceLen >= 0);
-
-    int64_t targetIndex = start;
-    int64_t sourceIndex = 0;
-
-    while (sourceIndex < sourceLen) {
-        String* p = Value(sourceIndex).toString(state);
-        ObjectHasPropertyResult exists = source.asObject()->hasIndexedProperty(state, p);
-        if (exists) {
-            Value element = exists.value(state, ObjectPropertyName(state, p), source);
-            if (!mappedValue.isEmpty()) {
-                Value args[] = { element, Value(sourceIndex), source };
-                ASSERT(!thisArg.isEmpty() && depth == 1);
-                element = Object::call(state, mappedValue, thisArg, 3, args);
-            }
-            if (depth > 0 && element.isObject() && element.asObject()->isArray(state)) {
-                int64_t elementLen = element.asObject()->length(state);
-                targetIndex = flattenIntoArray(state, target, element, elementLen, targetIndex, depth - 1);
-
-            } else {
-                if (targetIndex >= std::numeric_limits<int64_t>::max()) {
-                    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "invalid index");
-                }
-                target.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, targetIndex),
-                                                                    ObjectPropertyDescriptor(element, ObjectPropertyDescriptor::AllPresent));
-                targetIndex++;
-            }
-        }
-        sourceIndex++;
-    }
-    return targetIndex;
-}
-
-static Value builtinArrayIsArray(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ASSERT(argv != nullptr);
-
-    return Value(argv[0].isObject() && argv[0].asObject()->isArray(state));
-}
-
-// Array.from ( items [ , mapfn [ , thisArg ] ] )#
-static Value builtinArrayFrom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value items = argv[0];
-    Value mapfn;
-    if (argc > 1) {
-        mapfn = argv[1];
-    }
-    Value thisArg;
-    if (argc > 2) {
-        thisArg = argv[2];
-    }
-    // Let C be the this value.
-    Value C = thisValue;
-    Value T;
-    // If mapfn is undefined, let mapping be false.
-    bool mapping = false;
-    if (!mapfn.isUndefined()) {
-        // If IsCallable(mapfn) is false, throw a TypeError exception.
-        if (!mapfn.isCallable()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "argument map function should be undefined or function");
-        }
-        // If thisArg was supplied, let T be thisArg; else let T be undefined.
-        T = thisArg;
-        // Let mapping be true.
-        mapping = true;
-    }
-
-    // Let usingIterator be ? GetMethod(items, @@iterator).
-    Value usingIterator = Object::getMethod(state, items, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
-    // If usingIterator is not undefined, then
-    if (!usingIterator.isUndefined()) {
-        Object* A;
-        // If IsConstructor(C) is true, then
-        if (C.isConstructor()) {
-            // Let A be ? Construct(C).
-            A = Object::construct(state, C, 0, nullptr).toObject(state);
-        } else {
-            // Let A be ArrayCreate(0).
-            A = new ArrayObject(state);
-        }
-        // Let iteratorRecord be ? GetIterator(items, sync, usingIterator).
-        IteratorRecord* iteratorRecord = IteratorObject::getIterator(state, items, true, usingIterator);
-
-        // Let k be 0.
-        int64_t k = 0;
-        // Repeat
-        while (true) {
-            // If k ≥ 2^53-1, then
-            if (k >= ((1LL << 53LL) - 1LL)) {
-                // Let error be ThrowCompletion(a newly created TypeError object).
-                // Return ? IteratorClose(iteratorRecord, error).
-                Value throwCompletion = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("Got invalid index"));
-                return IteratorObject::iteratorClose(state, iteratorRecord, throwCompletion, true);
-            }
-            // Let Pk be ! ToString(k).
-            ObjectPropertyName pk(state, k);
-            // Let next be ? IteratorStep(iteratorRecord).
-            Optional<Object*> next = IteratorObject::iteratorStep(state, iteratorRecord);
-            // If next is false, then
-            if (!next.hasValue()) {
-                // Perform ? Set(A, "length", k, true).
-                A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(k), A);
-                // Return A.
-                return A;
-            }
-            // Let nextValue be ? IteratorValue(next).
-            Value nextValue = IteratorObject::iteratorValue(state, next.value());
-            Value mappedValue;
-            // If mapping is true, then
-            if (mapping) {
-                // Let mappedValue be Call(mapfn, T, « nextValue, k »).
-                // If mappedValue is an abrupt completion, return ? IteratorClose(iteratorRecord, mappedValue).
-                // Set mappedValue to mappedValue.[[Value]].
-                Value argv[] = { nextValue, Value(k) };
-                try {
-                    mappedValue = Object::call(state, mapfn, T, 2, argv);
-                } catch (const Value& v) {
-                    Value exceptionValue = v;
-                    return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-                }
-            } else {
-                mappedValue = nextValue;
-            }
-
-            try {
-                // Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue).
-                A->defineOwnPropertyThrowsException(state, pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
-            } catch (const Value& v) {
-                // If defineStatus is an abrupt completion, return ? IteratorClose(iteratorRecord, defineStatus).
-                Value exceptionValue = v;
-                return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-            }
-            // Increase k by 1.
-            k++;
-        }
-    }
-    // NOTE: items is not an Iterable so assume it is an array-like object.
-    // Let arrayLike be ! ToObject(items).
-    Object* arrayLike = items.toObject(state);
-    // Let len be ? ToLength(? Get(arrayLike, "length")).
-    uint64_t len = arrayLike->length(state);
-    // If IsConstructor(C) is true, then
-    Object* A;
-    if (C.isConstructor()) {
-        // Let A be ? Construct(C, « len »).
-        Value vlen(len);
-        A = Object::construct(state, C, 1, &vlen).toObject(state);
-    } else {
-        // Else,
-        // Let A be ? ArrayCreate(len).
-        A = new ArrayObject(state, len);
-    }
-
-    // Let k be 0.
-    uint64_t k = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ! ToString(k).
-        ObjectPropertyName Pk(state, k);
-        // Let kValue be ? Get(arrayLike, Pk).
-        Value kValue = arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike);
-        // If mapping is true, then
-        Value mappedValue;
-        if (mapping) {
-            // Let mappedValue be ? Call(mapfn, T, « kValue, k »).
-            Value argv[] = { kValue, Value(k) };
-            mappedValue = Object::call(state, mapfn, T, 2, argv);
-        } else {
-            // Else, let mappedValue be kValue.
-            mappedValue = kValue;
-        }
-        // Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
-        A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
-        // Increase k by 1.
-        k++;
-    }
-    // Perform ? Set(A, "length", len, true).
-    A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(len), A);
-    // Return A.
-    return A;
-}
-
-// Array.of ( ...items )
-static Value builtinArrayOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    size_t len = argc;
-    Value C = thisValue;
-
-    Object* A;
-    if (C.isConstructor()) {
-        Value arg[1] = { Value(len) };
-        A = Object::construct(state, C, 1, arg).toObject(state);
-    } else {
-        A = new ArrayObject(state, static_cast<uint64_t>(len));
-    }
-
-    size_t k = 0;
-    while (k < len) {
-        Value kValue = argv[k];
-        ObjectPropertyName Pk(state, k);
-        A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(kValue, ObjectPropertyDescriptor::AllPresent));
-        k++;
-    }
-    A->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(len), A);
-
-    return A;
-}
-
-static Value builtinArrayJoin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisBinded, Array, join);
-    int64_t len = thisBinded->length(state);
-    Value separator = argv[0];
-    String* sep;
-
-    if (separator.isUndefined()) {
-        sep = state.context()->staticStrings().asciiTable[(size_t)','].string();
-    } else {
-        sep = separator.toString(state);
-    }
-
-    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(thisBinded)) {
-        return String::emptyString;
-    }
-    ToStringRecursionPreventerItemAutoHolder holder(state, thisBinded);
-
-    StringBuilder builder;
-    int64_t prevIndex = 0;
-    int64_t curIndex = 0;
-    while (curIndex < len) {
-        if (curIndex != 0 && sep->length() > 0) {
-            if (static_cast<double>(builder.contentLength()) > static_cast<double>(STRING_MAXIMUM_LENGTH - (curIndex - prevIndex - 1) * (int64_t)sep->length())) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
-            }
-            while (curIndex - prevIndex > 1) {
-                builder.appendString(sep);
-                prevIndex++;
-            }
-            builder.appendString(sep);
-        }
-        Value elem = thisBinded->getIndexedProperty(state, Value(curIndex)).value(state, thisBinded);
-
-        if (!elem.isUndefinedOrNull()) {
-            builder.appendString(elem.toString(state));
-        }
-        prevIndex = curIndex;
-        if (elem.isUndefined()) {
-            struct Data {
-                bool exists;
-                int64_t cur;
-                int64_t ret;
-            } data;
-            data.exists = false;
-            data.cur = curIndex;
-            data.ret = len;
-
-            Value ptr = thisBinded;
-            while (ptr.isObject()) {
-                if (!ptr.asObject()->isOrdinary()) {
-                    curIndex++;
-                    break;
-                }
-                ptr.asObject()->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& name, const ObjectStructurePropertyDescriptor& desc, void* data) {
-                    int64_t index;
-                    Data* e = (Data*)data;
-                    int64_t* ret = &e->ret;
-                    Value key = name.toPlainValue(state);
-                    index = key.toNumber(state);
-                    if ((uint64_t)index != Value::InvalidIndexValue) {
-                        if (self->get(state, name).value(state, self).isUndefined()) {
-                            return true;
-                        }
-                        if (index > e->cur && e->ret > index) {
-                            e->ret = std::min(index, e->ret);
-                        }
-                    }
-                    return true;
-                },
-                                            &data);
-                ptr = ptr.asObject()->getPrototype(state);
-            }
-            curIndex = data.ret;
-        } else {
-            curIndex++;
-        }
-    }
-    if (sep->length() > 0) {
-        if (static_cast<double>(builder.contentLength()) > static_cast<double>(STRING_MAXIMUM_LENGTH - (curIndex - prevIndex - 1) * (int64_t)sep->length())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
-        }
-        while (curIndex - prevIndex > 1) {
-            builder.appendString(sep);
-            prevIndex++;
-        }
-    }
-    return builder.finalize(&state);
-}
-
-static Value builtinArrayReverse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reverse);
-    int64_t len = O->length(state);
-    int64_t middle = std::floor(len / 2);
-    int64_t lower = 0;
-    while (middle > lower) {
-        int64_t upper = len - lower - 1;
-        ObjectPropertyName upperP = ObjectPropertyName(state, upper);
-        ObjectPropertyName lowerP = ObjectPropertyName(state, lower);
-
-        auto lowerExists = O->hasIndexedProperty(state, Value(lower));
-        Value lowerValue;
-        if (lowerExists) {
-            lowerValue = lowerExists.value(state, lowerP, O);
-        }
-        auto upperExists = O->hasIndexedProperty(state, Value(upper));
-        Value upperValue;
-        if (upperExists) {
-            upperValue = upperExists.value(state, upperP, O);
-        }
-        if (lowerExists && upperExists) {
-            O->setThrowsException(state, lowerP, upperValue, O);
-            O->setThrowsException(state, upperP, lowerValue, O);
-        } else if (!lowerExists && upperExists) {
-            O->setThrowsException(state, lowerP, upperValue, O);
-            O->deleteOwnPropertyThrowsException(state, upperP);
-        } else if (lowerExists && !upperExists) {
-            O->deleteOwnPropertyThrowsException(state, lowerP);
-            O->setThrowsException(state, upperP, lowerValue, O);
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, lower, middle, result);
-            int64_t nextLower = result;
-            Object::nextIndexBackward(state, O, upper, middle, result);
-            int64_t nextUpper = result;
-            int64_t x = middle - nextLower;
-            int64_t y = nextUpper - middle;
-            int64_t lowerCandidate;
-            if (x > y) {
-                lowerCandidate = nextLower;
-            } else {
-                lowerCandidate = len - nextUpper - 1;
-            }
-            if (lower == lowerCandidate)
-                break;
-            lower = lowerCandidate;
-            continue;
-        }
-        lower++;
-    }
-
-    return O;
-}
-
-static Value builtinArraySort(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, sort);
-    Value cmpfn = argv[0];
-    if (!cmpfn.isUndefined() && !cmpfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
-    }
-    bool defaultSort = (argc == 0) || cmpfn.isUndefined();
-
-    int64_t len = thisObject->length(state);
-
-    thisObject->sort(state, len, [defaultSort, &cmpfn, &state](const Value& a, const Value& b) -> bool {
-        if (a.isEmpty() && b.isUndefined())
-            return false;
-        if (a.isUndefined() && b.isEmpty())
-            return true;
-        if (a.isEmpty() || a.isUndefined())
-            return false;
-        if (b.isEmpty() || b.isUndefined())
-            return true;
-        Value arg[2] = { a, b };
-        if (defaultSort) {
-            String* vala = a.toString(state);
-            String* valb = b.toString(state);
-            return *vala < *valb;
-        } else {
-            Value ret = Object::call(state, cmpfn, Value(), 2, arg);
-            return (ret.toNumber(state) < 0);
-        } });
-    return thisObject;
-}
-
-static Value builtinArraySplice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // TODO(ES6): the number of actual arguments is used.
-    // e.g. var arr = [1, 2, 3, 4, 5];
-    //      Different: arr.splice(2) vs. arr.splice(2, undefined)
-
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, splice);
-
-    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // Let relativeStart be ToInteger(start).
-    double relativeStart = argv[0].toInteger(state);
-
-    // If relativeStart is negative, let actualStart be max((len + relativeStart),0); else let actualStart be min(relativeStart, len).
-    int64_t actualStart = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
-
-    int64_t insertCount;
-    int64_t actualDeleteCount;
-
-    // If the number of actual arguments is 0, then
-    if (argc == 0) {
-        // Let insertCount be 0.
-        insertCount = 0;
-        // Let actualDeleteCount be 0.
-        actualDeleteCount = 0;
-    } else if (argc == 1) {
-        // Else if the number of actual arguments is 1, then
-        // Let insertCount be 0.
-        insertCount = 0;
-        // Let actualDeleteCount be len – actualStart.
-        actualDeleteCount = len - actualStart;
-    } else {
-        // Else,
-        // Let insertCount be the number of actual arguments minus 2.
-        insertCount = argc - 2;
-        // Let dc be ToInteger(deleteCount).
-        double dc = argv[1].toInteger(state);
-        // Let actualDeleteCount be min(max(dc,0), len – actualStart).
-        actualDeleteCount = std::min(std::max(dc, 0.0), (double)(len - actualStart));
-    }
-    // If len+insertCount−actualDeleteCount > 2^53-1, throw a TypeError exception.
-    CHECK_ARRAY_LENGTH(len + insertCount - actualDeleteCount > Value::maximumLength());
-    // Let A be ArraySpeciesCreate(O, actualDeleteCount).
-    Object* A = arraySpeciesCreate(state, O, actualDeleteCount);
-
-    // Let k be 0.
-    int64_t k = 0;
-
-    // Repeat, while k < actualDeleteCount
-    while (k < actualDeleteCount) {
-        // Let from be ToString(actualStart+k).
-        // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
-        // If fromPresent is true, then
-        // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
-        ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(actualStart + k));
-        if (fromValue) {
-            // Call the [[DefineOwnProperty]] internal method of A with arguments ToString(k), Property Descriptor {[[Value]]: fromValue, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
-            ObjectPropertyName from(state, Value(actualStart + k));
-            A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, k),
-                                                ObjectPropertyDescriptor(fromValue.value(state, from, O), ObjectPropertyDescriptor::AllPresent));
-        }
-        // Increment k by 1.
-        k++;
-    }
-    // Let setStatus be Set(A, "length", actualDeleteCount, true).
-    A->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(actualDeleteCount), A);
-
-    // Let items be an internal List whose elements are, in left to right order, the portion of the actual argument list starting with item1. The list will be empty if no such items are present.
-    Value* items = nullptr;
-    int64_t itemCount = 0;
-
-    if (argc > 2) {
-        items = argv + 2;
-        itemCount = argc - 2;
-    }
-
-    // If itemCount < actualDeleteCount, then
-    if (itemCount < actualDeleteCount) {
-        // Let k be actualStart.
-        k = actualStart;
-        // move [actualStart + deleteCnt, len) to [actualStart + insertCnt, len - deleteCnt + insertCnt)
-        while (k < len - actualDeleteCount) {
-            // Let from be ToString(k+actualDeleteCount).
-            int64_t from = k + actualDeleteCount;
-            // Let to be ToString(k+itemCount).
-            int64_t to = k + itemCount;
-            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
-            ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(from));
-            // If fromPresent is true, then
-            if (fromValue) {
-                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
-                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
-                O->setIndexedPropertyThrowsException(state, Value(to), fromValue.value(state, ObjectPropertyName(state, from), O));
-            } else {
-                // Else, fromPresent is false
-
-                // Call the [[Delete]] internal method of O with arguments to and true.
-                O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(to)));
-            }
-            k++;
-        }
-        // delete [len - deleteCnt + itemCount, len)
-        // Let k be len.
-        k = len;
-        // Repeat, while k > (len – actualDeleteCount + itemCount)
-        while (k > len - actualDeleteCount + itemCount) {
-            // Call the [[Delete]] internal method of O with arguments ToString(k–1) and true.
-            O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(k - 1)));
-            // Decrease k by 1.
-            k--;
-        }
-    } else if (itemCount > actualDeleteCount) {
-        // Else if itemCount > actualDeleteCount, then
-
-        // Let k be (len – actualDeleteCount).
-        k = len - actualDeleteCount;
-
-        // Repeat, while k > actualStart
-        while (k > actualStart) {
-            // Let from be ToString(k + actualDeleteCount – 1).
-            // Let to be ToString(k + itemCount – 1)
-
-            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
-            ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(k + actualDeleteCount - 1));
-            // If fromPresent is true, then
-            if (fromValue) {
-                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
-                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
-                ObjectPropertyName from(state, k + actualDeleteCount - 1);
-                O->setIndexedPropertyThrowsException(state, Value(k + itemCount - 1), fromValue.value(state, from, O));
-            } else {
-                // Else, fromPresent is false
-                // Call the [[Delete]] internal method of O with argument to and true.
-                ObjectPropertyName to(state, k + itemCount - 1);
-                O->deleteOwnPropertyThrowsException(state, to);
-            }
-            // Decrease k by 1.
-            k--;
-        }
-    }
-
-    // Let k be actualStart.
-    k = actualStart;
-
-    // while items is not empty
-    int64_t itemsIndex = 0;
-    while (itemsIndex < itemCount) {
-        // Remove the first element from items and let E be the value of that element.
-        Value E = items[itemsIndex++];
-        // Call the [[Put]] internal method of O with arguments ToString(k), E, and true.
-        O->setIndexedPropertyThrowsException(state, Value(k), E);
-        // Increase k by 1.
-        k++;
-    }
-
-    O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - actualDeleteCount + itemCount), O);
-    return A;
-}
-
-
-static Value builtinArrayToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, toString);
-    Value toString = thisObject->get(state, state.context()->staticStrings().join).value(state, thisObject);
-    if (!toString.isCallable()) {
-        toString = state.context()->globalObject()->objectPrototypeToString();
-    }
-    return Object::call(state, toString, thisObject, 0, nullptr);
-}
-
-static Value builtinArrayConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, concat);
-    Object* obj = arraySpeciesCreate(state, thisObject, 0);
-    int64_t n = 0;
-    for (size_t i = 0; i < argc + 1; i++) {
-        Value argi = (i == 0) ? thisObject : argv[i - 1];
-        if (argi.isObject()) {
-            Object* arr = argi.asObject();
-
-            // Let spreadable be IsConcatSpreadable(E).
-            bool spreadable = arr->isConcatSpreadable(state);
-
-            if (spreadable) {
-                // Let k be 0.
-                int64_t k = 0;
-                // Let len be the result of calling the [[Get]] internal method of E with argument "length".
-                int64_t len = arr->length(state);
-
-                // If n + len > 2^53 - 1, throw a TypeError exception.
-                CHECK_ARRAY_LENGTH(n + len > Value::maximumLength());
-
-                // Repeat, while k < len
-                while (k < len) {
-                    // Let exists be the result of calling the [[HasProperty]] internal method of E with P.
-                    ObjectHasPropertyResult exists = arr->hasIndexedProperty(state, Value(k));
-                    if (exists) {
-                        obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n + k)), ObjectPropertyDescriptor(exists.value(state, ObjectPropertyName(state, k), arr), ObjectPropertyDescriptor::AllPresent));
-                        k++;
-                    } else {
-                        int64_t result;
-                        Object::nextIndexForward(state, arr, k, len, result);
-                        k = result;
-                    }
-                }
-
-                n += len;
-                obj->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(n), obj);
-            } else {
-                // If n >= 2^53 - 1, throw a TypeError exception.
-                CHECK_ARRAY_LENGTH(n >= Value::maximumLength());
-
-                obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n)), ObjectPropertyDescriptor(arr, ObjectPropertyDescriptor::AllPresent));
-                n++;
-            }
-        } else {
-            obj->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n++)), ObjectPropertyDescriptor(argi, ObjectPropertyDescriptor::AllPresent));
-        }
-    }
-
-    return obj;
-}
-
-static Value builtinArraySlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, slice);
-    int64_t len = thisObject->length(state);
-    double relativeStart = argv[0].toInteger(state);
-    int64_t k = (relativeStart < 0) ? std::max((double)len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
-    int64_t kStart = k;
-    double relativeEnd = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
-    int64_t finalEnd = (relativeEnd < 0) ? std::max((double)len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
-
-    int64_t n = 0;
-    // Let count be max(final - k, 0).
-    // Let A be ArraySpeciesCreate(O, count).
-    Object* ArrayObject = arraySpeciesCreate(state, thisObject, std::max(((int64_t)finalEnd - (int64_t)k), (int64_t)0));
-    while (k < finalEnd) {
-        ObjectHasPropertyResult exists = thisObject->hasIndexedProperty(state, Value(k));
-        if (exists) {
-            ArrayObject->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(n)),
-                                                          ObjectPropertyDescriptor(exists.value(state, ObjectPropertyName(state, k), thisObject), ObjectPropertyDescriptor::AllPresent));
-            k++;
-            n++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, thisObject, k, len, result);
-            n += result - k;
-            k = result;
-        }
-    }
-    if (finalEnd - kStart > 0) {
-        ArrayObject->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(finalEnd - kStart), Value(ArrayObject));
-    } else {
-        ArrayObject->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), Value(ArrayObject));
-    }
-    return ArrayObject;
-}
-
-static Value builtinArrayForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, forEach);
-    int64_t len = thisObject->length(state);
-
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1)
-        T = argv[1];
-
-    int64_t k = 0;
-    while (k < len) {
-        Value Pk = Value(k);
-        auto res = thisObject->hasProperty(state, ObjectPropertyName(state, Pk));
-        if (res) {
-            Value kValue = res.value(state, ObjectPropertyName(state, k), thisObject);
-            Value args[3] = { kValue, Pk, thisObject };
-            Object::call(state, callbackfn, T, 3, args);
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, thisObject, k, len, result);
-            k = result;
-            continue;
-        }
-    }
-    return Value();
-}
-
-static Value builtinArrayIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, indexOf);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If len is 0, return -1.
-    if (len == 0) {
-        return Value(-1);
-    }
-
-    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
-    double n = 0;
-    if (argc > 1) {
-        n = argv[1].toInteger(state);
-    }
-
-    // If n ≥ len, return -1.
-    if (n >= len) {
-        return Value(-1);
-    }
-
-    double doubleK;
-    // If n ≥ 0, then
-    if (n >= 0) {
-        // Let k be n.
-        doubleK = (n == -0) ? 0 : n;
-    } else {
-        // Else, n<0
-        // Let k be len - abs(n).
-        doubleK = len - std::abs(n);
-
-        // If k is less than 0, then let k be 0.
-        if (doubleK < 0) {
-            doubleK = 0;
-        }
-    }
-
-    ASSERT(doubleK >= 0);
-    int64_t k = doubleK;
-
-    // Repeat, while k<len
-    while (k < len) {
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
-        auto kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
-            Value elementK = kPresent.value(state, ObjectPropertyName(state, k), O);
-
-            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
-            if (elementK.equalsTo(state, argv[0])) {
-                // If same is true, return k.
-                return Value(k);
-            }
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-            continue;
-        }
-        // Increase k by 1.
-        k++;
-    }
-
-    // Return -1.
-    return Value(-1);
-}
-
-static Value builtinArrayLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, lastIndexOf);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If len is 0, return -1.
-    if (len == 0) {
-        return Value(-1);
-    }
-
-    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
-    double n;
-    if (argc > 1) {
-        n = argv[1].toInteger(state);
-    } else {
-        n = len - 1;
-    }
-
-    // If n ≥ 0, then let k be min(n, len – 1).
-    int64_t k;
-    if (n >= 0) {
-        k = (n == -0) ? 0 : std::min(n, len - 1.0);
-    } else {
-        // Else, n < 0
-        // Let k be len - abs(n).
-        k = len - std::abs(n);
-    }
-
-    // Repeat, while k≥ 0
-    while (k >= 0) {
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
-        auto kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
-            Value elementK = kPresent.value(state, ObjectPropertyName(state, k), O);
-
-            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
-            if (elementK.equalsTo(state, argv[0])) {
-                // If same is true, return k.
-                return Value(k);
-            }
-        } else {
-            int64_t result;
-            Object::nextIndexBackward(state, O, k, -1, result);
-            k = result;
-            continue;
-        }
-        // Decrease k by 1.
-        k--;
-    }
-
-    // Return -1.
-    return Value(-1);
-}
-
-static Value builtinArrayEvery(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, every);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1)
-        T = argv[1];
-
-    // Let k be 0.
-    int64_t k = 0;
-
-    while (k < len) {
-        // Let Pk be ToString(k).
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        auto kPresent = O->hasIndexedProperty(state, Value(k));
-
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
-            // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-            Value args[] = { kValue, Value(k), O };
-            Value testResult = Object::call(state, callbackfn, T, 3, args);
-
-            if (!testResult.toBoolean(state)) {
-                return Value(false);
-            }
-
-            // Increae k by 1.
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-        }
-    }
-    return Value(true);
-}
-
-static Value builtinArrayFill(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, fill);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // Let relativeStart be ToInteger(start).
-    double relativeStart = 0;
-    if (argc > 1) {
-        relativeStart = argv[1].toInteger(state);
-    }
-
-    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
-    int64_t k = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
-
-    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
-    double relativeEnd = len;
-    if (argc > 2 && !argv[2].isUndefined()) {
-        relativeEnd = argv[2].toInteger(state);
-    }
-
-    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
-    int64_t fin = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
-
-    Value value = argv[0];
-    while (k < fin) {
-        O->setIndexedPropertyThrowsException(state, Value(k), value);
-        k++;
-    }
-    // return O.
-    return O;
-}
-
-static Value builtinArrayFilter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, filter);
-
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1)
-        T = argv[1];
-
-    // Let A be ArraySpeciesCreate(O, 0).
-    Object* A = arraySpeciesCreate(state, O, 0);
-
-    // Let k be 0.
-    int64_t k = 0;
-    // Let to be 0.
-    int64_t to = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ToString(k).
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
-
-            // Let selected be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-            Value v[] = { kValue, Value(k), O };
-            Value selected = Object::call(state, callbackfn, T, 3, v);
-
-            // If ToBoolean(selected) is true, then
-            if (selected.toBoolean(state)) {
-                // Let status be CreateDataPropertyOrThrow (A, ToString(to), kValue).
-                ASSERT(A != nullptr);
-                A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(to)), ObjectPropertyDescriptor(kValue, ObjectPropertyDescriptor::AllPresent));
-                // Increase to by 1
-                to++;
-            }
-
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-        }
-        // Increase k by 1.
-    }
-
-    // Return A.
-    return A;
-}
-
-static Value builtinArrayMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, map);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1)
-        T = argv[1];
-
-    // Let A be ArraySpeciesCreate(O, len).
-    Object* A = arraySpeciesCreate(state, O, len);
-
-    // Let k be 0.
-    int64_t k = 0;
-
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ToString(k).
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        auto kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            auto Pk = ObjectPropertyName(state, k);
-            Value kValue = kPresent.value(state, Pk, O);
-            // Let mappedValue be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-            Value v[] = { kValue, Value(k), O };
-            Value mappedValue = Object::call(state, callbackfn, T, 3, v);
-            // Let status be CreateDataPropertyOrThrow (A, Pk, mappedValue).
-            A->defineOwnPropertyThrowsException(state, Pk, ObjectPropertyDescriptor(mappedValue, ObjectPropertyDescriptor::AllPresent));
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-        }
-        // Increase k by 1.
-    }
-
-    return A;
-}
-
-static Value builtinArraySome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, some);
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().some.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    Value T;
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let k be 0.
-    int64_t k = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ToString(k).
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            ObjectPropertyName Pk(state, k);
-            Value kValue = kPresent.value(state, Pk, O);
-            // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-            Value argv[] = { kValue, Value(k), O };
-            Value testResult = Object::call(state, callbackfn, T, 3, argv);
-            // If ToBoolean(testResult) is true, return true.
-            if (testResult.toBoolean(state)) {
-                return Value(true);
-            }
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-            continue;
-        }
-        // Increase k by 1.
-        k++;
-    }
-    // Return false.
-    return Value(false);
-}
-
-// Array.prototype.includes ( searchElement [ , fromIndex ] )
-static Value builtinArrayIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, includes);
-    // Let len be ? ToLength(? Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If len is 0, return false.
-    if (len == 0) {
-        return Value(false);
-    }
-
-    Value searchElement = argv[0];
-    // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
-    double n = argc >= 2 ? argv[1].toInteger(state) : 0;
-    double doubleK;
-    // If n ≥ 0, then
-    if (n >= 0) {
-        // Let k be n.
-        doubleK = n;
-    } else {
-        // Else n < 0,
-        // Let k be len + n.
-        doubleK = len + n;
-    }
-
-    // If k < 0, let k be 0.
-    if (doubleK < 0) {
-        doubleK = 0;
-    }
-
-    ASSERT(doubleK >= 0);
-
-    // Repeat, while k < len
-    while (doubleK < len) {
-        // Let elementK be the result of ? Get(O, ! ToString(k)).
-        Value elementK = O->get(state, ObjectPropertyName(state, Value(doubleK))).value(state, O);
-        // If SameValueZero(searchElement, elementK) is true, return true.
-        if (elementK.equalsToByTheSameValueZeroAlgorithm(state, searchElement)) {
-            return Value(true);
-        }
-        // Increase k by 1.
-        doubleK++;
-    }
-
-    // Return false.
-    return Value(false);
-}
-
-static Value builtinArrayToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sup-array.prototype.tolocalestring
-    // Let array be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(array, Array, toLocaleString);
-
-    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(array)) {
-        return String::emptyString;
-    }
-    ToStringRecursionPreventerItemAutoHolder holder(state, array);
-
-    // Let len be ? ToLength(? Get(array, "length")).
-    uint64_t len = array->length(state);
-
-    // Let separator be the String value for the list-separator String appropriate for the host environment’s current locale (this is derived in an implementation-defined way).
-    String* separator = state.context()->staticStrings().asciiTable[(size_t)','].string();
-
-    // Let R be the empty String.
-    String* R = String::emptyString;
-
-    // Let k be 0.
-    uint64_t k = 0;
-
-    // Repeat, while k < len
-    while (k < len) {
-        // If k > 0, then
-        if (k > 0) {
-            // Set R to the string-concatenation of R and separator.
-            StringBuilder builder;
-            builder.appendString(R);
-            builder.appendString(separator);
-            R = builder.finalize(&state);
-        }
-        // Let nextElement be ? Get(array, ! ToString(k)).
-        Value nextElement = array->getIndexedProperty(state, Value(k)).value(state, array);
-        // If nextElement is not undefined or null, then
-        if (!nextElement.isUndefinedOrNull()) {
-            // Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)).
-            Value func = nextElement.toObject(state)->get(state, state.context()->staticStrings().toLocaleString).value(state, nextElement);
-            String* S = Object::call(state, func, nextElement, argc, argv).toString(state);
-            // Set R to the string-concatenation of R and S.
-            StringBuilder builder;
-            builder.appendString(R);
-            builder.appendString(S);
-            R = builder.finalize(&state);
-        }
-        // Increase k by 1.
-        k++;
-    }
-
-    // Return R.
-    return R;
-}
-
-static Value builtinArrayReduce(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reduce);
-    int64_t len = O->length(state); // 2-3
-    Value callbackfn = argv[0];
-    Value initialValue = Value(Value::EmptyValue);
-    if (argc > 1) {
-        initialValue = argv[1];
-    }
-
-    if (!callbackfn.isCallable()) // 4
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-
-    if (len == 0 && (initialValue.isUndefined() || initialValue.isEmpty())) // 5
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-
-    int64_t k = 0; // 6
-    Value accumulator;
-    if (!initialValue.isEmpty()) { // 7
-        accumulator = initialValue;
-    } else { // 8
-        ObjectHasPropertyResult kPresent; // 8.a
-        while (!kPresent && k < len) { // 8.b
-            kPresent = O->hasIndexedProperty(state, Value(k)); // 8.b.ii
-            if (kPresent) {
-                accumulator = kPresent.value(state, ObjectPropertyName(state, k), O);
-            }
-            k++; // 8.b.iv
-        }
-        if (!kPresent)
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-    }
-    while (k < len) { // 9
-        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k)); // 9.b
-        if (kPresent) { // 9.c
-            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O); // 9.c.i
-            const int fnargc = 4;
-            Value fnargs[] = { accumulator, kValue, Value(k), O };
-            accumulator = Object::call(state, callbackfn, Value(), fnargc, fnargs);
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            k = result;
-        }
-    }
-    return accumulator;
-}
-
-static Value builtinArrayReduceRight(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, reduceRight);
-
-    // Let lenValue be the result of calling the [[Get]] internal method of O with the argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true,
-                                       state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If len is 0 and initialValue is not present, throw a TypeError exception.
-    if (len == 0 && argc < 2) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-    }
-
-    // Let k be len-1.
-    int64_t k = len - 1;
-
-    Value accumulator;
-    // If initialValue is present, then
-    if (argc > 1) {
-        // Set accumulator to initialValue.
-        accumulator = argv[1];
-    } else {
-        // Else, initialValue is not present
-        // Let kPresent be false.
-        ObjectHasPropertyResult kPresent;
-
-        // Repeat, while kPresent is false and k ≥ 0
-        while (!kPresent && k >= 0) {
-            // Let Pk be ToString(k).
-            // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-            kPresent = O->hasIndexedProperty(state, Value(k));
-
-            // If kPresent is true, then
-            if (kPresent) {
-                // Let accumulator be the result of calling the [[Get]] internal method of O with argument Pk.
-                accumulator = kPresent.value(state, ObjectPropertyName(state, k), O);
-            }
-
-            // Decrease k by 1.
-            int64_t result;
-            Object::nextIndexBackward(state, O, k, -1, result);
-            k = result;
-        }
-        // If kPresent is false, throw a TypeError exception.
-        if (!kPresent) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-        }
-    }
-
-    // Repeat, while k ≥ 0
-    while (k >= 0) {
-        // Let Pk be ToString(k).
-        ObjectPropertyName Pk(state, k);
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        ObjectHasPropertyResult kPresent = O->hasIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            Value kValue = kPresent.value(state, ObjectPropertyName(state, k), O);
-
-            // Let accumulator be the result of calling the [[Call]] internal method of callbackfn with undefined as the this value and argument list containing accumulator, kValue, k, and O.
-            Value v[] = { accumulator, kValue, Value(k), O };
-            accumulator = Object::call(state, callbackfn, Value(), 4, v);
-        }
-
-        // Decrease k by 1.
-        int64_t result;
-        Object::nextIndexBackward(state, O, k, -1, result);
-        k = result;
-    }
-
-    // Return accumulator.
-    return accumulator;
-}
-
-static Value builtinArrayPop(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, pop);
-
-    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
-    // Let len be ToUint32(lenVal).
-    int64_t len = O->length(state);
-
-    // If len is zero,
-    if (len == 0) {
-        // Call the [[Put]] internal method of O with arguments "length", 0, and true.
-        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), O);
-        // Return undefined.
-        return Value();
-    } else {
-        // Else, len > 0
-        // Let indx be ToString(len–1).
-        ObjectPropertyName indx(state, len - 1);
-        // Let element be the result of calling the [[Get]] internal method of O with argument indx.
-        Value element = O->get(state, indx).value(state, O);
-        // Call the [[Delete]] internal method of O with arguments indx and true.
-        O->deleteOwnPropertyThrowsException(state, indx);
-        // Call the [[Put]] internal method of O with arguments "length", indx, and true.
-        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - 1), O);
-        // Return element.
-        return element;
-    }
-}
-
-static Value builtinArrayPush(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Array.prototype.push ( [ item1 [ , item2 [ , … ] ] ] )
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, push);
-
-    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t n = O->length(state);
-
-    // If len + argCount > 2^53 - 1, throw a TypeError exception.
-    CHECK_ARRAY_LENGTH((uint64_t)n + argc > Value::maximumLength());
-
-    // Let items be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.
-    // Repeat, while items is not empty
-    // Remove the first element from items and let E be the value of the element.
-    for (size_t i = 0; i < argc; i++) {
-        // Call the [[Put]] internal method of O with arguments ToString(n), E, and true.
-        O->setIndexedPropertyThrowsException(state, Value(n), argv[i]);
-        // Increase n by 1.
-        n++;
-    }
-
-    // Call the [[Put]] internal method of O with arguments "length", n, and true.
-    O->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, state.context()->staticStrings().length), Value(n), O);
-
-    // Return n.
-    return Value(n);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-array.prototype.flat
-// Array.prototype.flat( [ depth ] )
-static Value builtinArrayFlat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, flat);
-    int64_t sourceLen = O->length(state);
-    double depthNum = 1;
-    if (argc > 0 && !argv[0].isUndefined()) {
-        depthNum = argv[0].toInteger(state);
-    }
-    Object* A = arraySpeciesCreate(state, O, 0);
-    flattenIntoArray(state, A, O, sourceLen, 0, depthNum);
-
-    return A;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-array.prototype.flatmap
-// Array.prototype.flatMap ( mapperFunction [ , thisArg ] )
-static Value builtinArrayFlatMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, flatMap);
-    int64_t sourceLen = O->length(state);
-    if (!argv[0].isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().flatMap.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
-    }
-    Value t;
-    if (argc > 1) {
-        t = argv[1];
-    }
-    Object* A = arraySpeciesCreate(state, O, 0);
-    flattenIntoArray(state, A, O, sourceLen, 0, 1, argv[0], t);
-    return A;
-}
-
-static Value builtinArrayShift(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, shift);
-    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-    // If len is zero, then
-    if (len == 0) {
-        // Call the [[Put]] internal method of O with arguments "length", 0, and true.
-        O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(0), O);
-        // Return undefined.
-        return Value();
-    }
-    // Let first be the result of calling the [[Get]] internal method of O with argument "0".
-    Value first = O->get(state, ObjectPropertyName(state, Value(0))).value(state, O);
-    // Let k be 1.
-    int64_t k = 1;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let from be ToString(k).
-        ObjectPropertyName from(state, k);
-        // Let to be ToString(k–1).
-        ObjectPropertyName to(state, k - 1);
-        // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
-        auto fromPresent = O->hasIndexedProperty(state, Value(k));
-
-        // If fromPresent is true, then
-        if (fromPresent) {
-            // Let fromVal be the result of calling the [[Get]] internal method of O with argument from.
-            Value fromVal = fromPresent.value(state, from, O);
-            // Call the [[Put]] internal method of O with arguments to, fromVal, and true.
-            O->setThrowsException(state, to, fromVal, O);
-        } else {
-            // Else, fromPresent is false
-            // Call the [[Delete]] internal method of O with arguments to and true.
-            O->deleteOwnPropertyThrowsException(state, to);
-        }
-
-        // Increase k by 1.
-        if (fromPresent) {
-            k++;
-        } else {
-            int64_t result;
-            Object::nextIndexForward(state, O, k, len, result);
-            int64_t r = result;
-            if (r > k) {
-                k = r;
-            } else {
-                k--;
-            }
-        }
-    }
-    // Call the [[Delete]] internal method of O with arguments ToString(len–1) and true.
-    O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(len - 1)));
-    // Call the [[Put]] internal method of O with arguments "length", (len–1) , and true.
-    O->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length), Value(len - 1), O);
-    // Return first.
-    return first;
-}
-
-static Value builtinArrayUnshift(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, unshift);
-    // Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
-    // Let len be ToLength(Get(O, "length")).
-    int64_t len = O->length(state);
-
-    // Let argCount be the number of actual arguments.
-    int64_t argCount = argc;
-    // Let k be len.
-    int64_t k = len;
-
-    // If argCount > 0, then
-    // this line add in newer version ECMAScript than ECMAScript 5.1
-    // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.unshift
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.13
-    if (argCount) {
-        // If len + argCount > 2^53 - 1, throw a TypeError exception.
-        CHECK_ARRAY_LENGTH(len + argCount > Value::maximumLength());
-
-        // Repeat, while k > 0,
-        while (k > 0) {
-            // Let from be ToString(k–1).
-            // Let to be ToString(k+argCount –1).
-            ObjectPropertyName to(state, k + argCount - 1);
-
-            // Let fromPresent be the result of calling the [[HasProperty]] internal method of O with argument from.
-            ObjectHasPropertyResult fromPresent = O->hasIndexedProperty(state, Value(k - 1));
-            // If fromPresent is true, then
-            if (fromPresent) {
-                // Let fromValue be the result of calling the [[Get]] internal method of O with argument from.
-                ObjectPropertyName from(state, k - 1);
-                Value fromValue = fromPresent.value(state, from, O);
-                // Call the [[Put]] internal method of O with arguments to, fromValue, and true.
-                O->setThrowsException(state, to, fromValue, O);
-            } else {
-                // Else, fromPresent is false
-                // Call the [[Delete]] internal method of O with arguments to, and true.
-                O->deleteOwnPropertyThrowsException(state, to);
-            }
-
-            if (fromPresent) {
-                // Decrease k by 1.
-                k--;
-            } else {
-                int64_t result;
-                Object::nextIndexBackward(state, O, k, -1, result);
-                int64_t r = std::max(result + 1, result - argCount + 1);
-                if (r < k && std::abs(r - k) > argCount) {
-                    k = r;
-                } else {
-                    k--;
-                }
-            }
-        }
-
-        // Let j be 0.
-        int64_t j = 0;
-        // Let items be an internal List whose elements are, in left to right order, the arguments that were passed to this function invocation.
-        Value* items = argv;
-
-        // Repeat, while items is not empty
-        while (j < argCount) {
-            // Remove the first element from items and let E be the value of that element.
-            Value E = items[j];
-            // Call the [[Put]] internal method of O with arguments ToString(j), E, and true.
-            O->setThrowsException(state, ObjectPropertyName(state, Value(j)), E, O);
-            // Increase j by 1.
-            j++;
-        }
-    }
-
-    // Call the [[Put]] internal method of O with arguments "length", len+argCount, and true.
-    O->setThrowsException(state, state.context()->staticStrings().length, Value(len + argCount), O);
-
-    // Return len+argCount.
-    return Value(len + argCount);
-}
-
-// Array.prototype.find ( predicate [ , thisArg ] )#
-static Value builtinArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, find);
-    // Let len be ? ToLength(? Get(O, "length")).
-    double len = O->length(state);
-    // If IsCallable(predicate) is false, throw a TypeError exception.
-    if (!argv[0].isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    Value T;
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (argc >= 2) {
-        T = argv[1];
-    }
-    // Let k be 0.
-    double k = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ! ToString(k).
-        // Let kValue be ? Get(O, Pk).
-        Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
-        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
-        Value v[] = { kValue, Value(k), O };
-        bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
-        // If testResult is true, return kValue.
-        if (testResult) {
-            return kValue;
-        }
-        // Increase k by 1.
-        k++;
-    }
-    // Return undefined.
-    return Value();
-}
-
-// Array.prototype.findIndex ( predicate [ , thisArg ] )#
-static Value builtinArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, findIndex);
-    // Let len be ? ToLength(? Get(O, "length")).
-    double len = O->length(state);
-    // If IsCallable(predicate) is false, throw a TypeError exception.
-    if (!argv[0].isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    Value T;
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (argc >= 2) {
-        T = argv[1];
-    }
-    // Let k be 0.
-    double k = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let Pk be ! ToString(k).
-        // Let kValue be ? Get(O, Pk).
-        Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
-        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
-        Value v[] = { kValue, Value(k), O };
-        bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
-        // If testResult is true, return k.
-        if (testResult) {
-            return Value(k);
-        }
-        // Increase k by 1.
-        k++;
-    }
-    // Return -1
-    return Value(-1);
-}
-
-// Array.prototype.copyWithin (target, start [ , end ] )
-static Value builtinArrayCopyWithin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, copyWithin);
-    // Let len be ToLength(Get(O, "length")).
-    double len = O->length(state);
-    // Let relativeTarget be ToInteger(target).
-    double relativeTarget = argv[0].toInteger(state);
-    // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len).
-    double to = (relativeTarget < 0.0) ? std::max((len + relativeTarget), 0.0) : std::min(relativeTarget, len);
-    // Let relativeStart be ToInteger(start).
-    double relativeStart = argv[1].toInteger(state);
-    // If relativeStart < 0, let from be max((len + relativeStart),0); else let from be min(relativeStart, len).
-    double from = (relativeStart < 0.0) ? std::max((len + relativeStart), 0.0) : std::min(relativeStart, len);
-    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
-    double relativeEnd = (argc < 3 || argv[2].isUndefined()) ? len : argv[2].toInteger(state);
-    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
-    double finalEnd = (relativeEnd < 0.0) ? std::max((len + relativeEnd), 0.0) : std::min(relativeEnd, len);
-    // Let count be min(final-from, len-to).
-    double count = std::min(finalEnd - from, len - to);
-    int8_t direction;
-    // If from<to and to<from+count
-    if (from < to && to < from + count) {
-        // Let direction be -1.
-        direction = -1;
-        // Let from be from + count -1.
-        from = from + count - 1;
-        // Let to be to + count -1.
-        to = to + count - 1;
-    } else {
-        // Let direction = 1.
-        direction = 1;
-    }
-
-    int64_t intCount = count;
-    int64_t intFrom = from;
-    int64_t intTo = to;
-
-    // Repeat, while count > 0
-    while (intCount > 0) {
-        // Let fromPresent be HasProperty(O, fromKey).
-        ObjectHasPropertyResult fromValue = O->hasIndexedProperty(state, Value(intFrom));
-        // If fromPresent is true, then
-        if (fromValue) {
-            // Let setStatus be Set(O, toKey, fromVal, true).
-            O->setIndexedPropertyThrowsException(state, Value(intTo), fromValue.value(state, ObjectPropertyName(state, intFrom), O));
-        } else {
-            // Let deleteStatus be DeletePropertyOrThrow(O, toKey).
-            O->deleteOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(intTo)));
-        }
-        // Let from be from + direction.
-        intFrom += direction;
-        // Let to be to + direction.
-        intTo += direction;
-        // Let count be count − 1.
-        intCount--;
-    }
-    // Return O.
-    return O;
-}
-
-static Value builtinArrayKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, keys);
-    return M->keys(state);
-}
-
-static Value builtinArrayValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, values);
-    return M->values(state);
-}
-
-static Value builtinArrayEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(M, Array, entries);
-    return M->entries(state);
-}
-
-static Value builtinArrayIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isArrayIteratorObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-
-    ArrayIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asArrayIteratorObject();
-    return iter->next(state);
-}
-
-static Value builtinArrayAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(obj, Array, entries);
-    size_t len = obj->length(state);
-    double relativeStart = argv[0].toInteger(state);
-    if (relativeStart < 0) {
-        relativeStart = len + relativeStart;
-    }
-    if (relativeStart < 0 || relativeStart >= len) {
-        return Value();
-    }
-    return obj->getIndexedProperty(state, Value(relativeStart)).value(state, thisValue);
-}
-
-void GlobalObject::installArray(ExecutionState& state)
-{
-    m_array = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Array, builtinArrayConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_array->setGlobalIntrinsicObject(state);
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_array->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    m_arrayPrototype = new ArrayPrototypeObject(state);
-    m_arrayPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_arrayPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().isArray),
-                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().isArray, builtinArrayIsArray, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().from),
-                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().from, builtinArrayFrom, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_array->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().of),
-                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().of, builtinArrayOf, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().concat),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().concat, builtinArrayConcat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinArrayForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().indexOf),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().indexOf, builtinArrayIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndexOf),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().lastIndexOf, builtinArrayLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().join),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().join, builtinArrayJoin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sort),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sort, builtinArraySort, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().splice),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().splice, builtinArraySplice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().slice),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().slice, builtinArraySlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().every),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().every, builtinArrayEvery, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().fill),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().fill, builtinArrayFill, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().includes),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().includes, builtinArrayIncludes, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().filter),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().filter, builtinArrayFilter, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reduce),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reduce, builtinArrayReduce, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reduceRight),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reduceRight, builtinArrayReduceRight, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().pop),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().pop, builtinArrayPop, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().push),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().push, builtinArrayPush, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().shift),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().shift, builtinArrayShift, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reverse),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reverse, builtinArrayReverse, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toString),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinArrayToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().map),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().map, builtinArrayMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().some),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().some, builtinArraySome, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinArrayToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().unshift),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().unshift, builtinArrayUnshift, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keys, builtinArrayKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().find),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().find, builtinArrayFind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().findIndex),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().findIndex, builtinArrayFindIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().copyWithin),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().copyWithin, builtinArrayCopyWithin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().flat),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().flat, builtinArrayFlat, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().flatMap),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().flatMap, builtinArrayFlatMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().at),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().at, builtinArrayAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    Object* blackList = new Object(state);
-    blackList->markThisObjectDontNeedStructureTransitionTable();
-    blackList->setPrototype(state, Value(Value::Null));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().at), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().copyWithin), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().entries), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().fill), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().find), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().findIndex), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keys), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().values), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().includes), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().flat), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-    blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().flatMap), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
-
-    FunctionObject* values = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinArrayValues, 0, NativeFunctionInfo::Strict));
-    // Well-Known Intrinsic Objects : %ArrayProto_values%
-    // The initial value of the values data property of %ArrayPrototype%
-    m_arrayPrototypeValues = values;
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values),
-                                                       ObjectPropertyDescriptor(values, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                       ObjectPropertyDescriptor(values,
-                                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
-                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinArrayEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().unscopables),
-                                                       ObjectPropertyDescriptor(blackList, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_array->setFunctionPrototype(state, m_arrayPrototype);
-
-    m_arrayIteratorPrototype = new Object(state, m_iteratorPrototype);
-    m_arrayIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_arrayIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinArrayIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                               ObjectPropertyDescriptor(Value(String::fromASCII("Array Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Array),
-                      ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinArrayBuffer.cpp
deleted file mode 100644 (file)
index e9e91e8..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "ArrayBufferObject.h"
-
-namespace Escargot {
-
-// https://262.ecma-international.org/#sec-arraybuffer-constructor
-static Value builtinArrayBufferConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    uint64_t byteLength = argv[0].toIndex(state);
-    if (byteLength == Value::InvalidIndexValue) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
-    }
-
-    return ArrayBufferObject::allocateArrayBuffer(state, newTarget.value(), byteLength);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-arraybuffer.isview
-static Value builtinArrayBufferIsView(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-
-    Object* obj = argv[0].asObject();
-    if (obj->isTypedArrayObject() || obj->isDataViewObject()) {
-        return Value(true);
-    }
-
-    return Value(false);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-arraybuffer.prototype.bytelength
-static Value builtinArrayBufferByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-
-    ArrayBufferObject* obj = thisValue.asObject()->asArrayBufferObject();
-#if defined(ENABLE_THREADING)
-    if (obj->isSharedArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-#endif
-
-    if (obj->isDetachedBuffer()) {
-        return Value(0);
-    }
-
-    return Value(obj->byteLength());
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-arraybuffer.prototype.slice
-static Value builtinArrayBufferSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-
-    ArrayBufferObject* obj = thisValue.asObject()->asArrayBufferObject();
-#if defined(ENABLE_THREADING)
-    if (obj->isSharedArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-#endif
-    obj->throwTypeErrorIfDetached(state);
-
-    double len = obj->byteLength();
-    double relativeStart = argv[0].toInteger(state);
-    size_t first = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, len);
-    double relativeEnd = argv[1].isUndefined() ? len : argv[1].toInteger(state);
-    double final_ = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, len);
-    size_t newLen = std::max((int)final_ - (int)first, 0);
-
-    Value constructor = obj->speciesConstructor(state, state.context()->globalObject()->arrayBuffer());
-    Value arguments[] = { Value(newLen) };
-    Object* newValue = Object::construct(state, constructor, 1, arguments).toObject(state);
-    if (!newValue->isArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
-    }
-
-    ArrayBufferObject* newObject = newValue->asArrayBufferObject();
-    newObject->throwTypeErrorIfDetached(state);
-
-    if (newObject == obj) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
-    }
-
-    if (newObject->byteLength() < newLen) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().ArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor ArrayBuffer is not valid ArrayBuffer");
-    }
-    obj->throwTypeErrorIfDetached(state);
-
-    newObject->fillData(obj->data() + first, newLen);
-    return newObject;
-}
-
-void GlobalObject::installArrayBuffer(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    m_arrayBuffer = new NativeFunctionObject(state, NativeFunctionInfo(strings->ArrayBuffer, builtinArrayBufferConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_arrayBuffer->setGlobalIntrinsicObject(state);
-
-    m_arrayBuffer->defineOwnProperty(state, ObjectPropertyName(strings->isView),
-                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isView, builtinArrayBufferIsView, 1, NativeFunctionInfo::Strict)),
-                                                              (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayBufferPrototype = new Object(state, m_objectPrototype);
-    m_arrayBufferPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_arrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_arrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                             ObjectPropertyDescriptor(Value(strings->ArrayBuffer.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_arrayBuffer->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    JSGetterSetter gs(
-        new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinArrayBufferByteLengthGetter, 0, NativeFunctionInfo::Strict)),
-        Value(Value::EmptyValue));
-    ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-    m_arrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
-    m_arrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
-                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinArrayBufferSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_arrayBuffer->setFunctionPrototype(state, m_arrayBufferPrototype);
-
-    defineOwnProperty(state, ObjectPropertyName(strings->ArrayBuffer),
-                      ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFromSyncIterator.cpp
deleted file mode 100644 (file)
index 5a81337..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/VMInstance.h"
-#include "runtime/AsyncFromSyncIteratorObject.h"
-#include "runtime/PromiseObject.h"
-#include "runtime/ErrorObject.h"
-#include "runtime/IteratorObject.h"
-#include "runtime/NativeFunctionObject.h"
-
-namespace Escargot {
-
-class ScriptAsyncFromSyncIteratorHelperFunctionObject : public NativeFunctionObject {
-public:
-    ScriptAsyncFromSyncIteratorHelperFunctionObject(ExecutionState& state, NativeFunctionInfo info, bool done)
-        : NativeFunctionObject(state, info)
-        , m_done(done)
-    {
-    }
-
-    bool m_done;
-};
-
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-async-from-sync-iterator-value-unwrap-functions
-static Value asyncFromSyncIteratorValueUnwrapLogic(ExecutionState& state, ScriptAsyncFromSyncIteratorHelperFunctionObject* activeFunctionObject, const Value& value)
-{
-    // Let F be the active function object.
-    ScriptAsyncFromSyncIteratorHelperFunctionObject* F = activeFunctionObject;
-    // Return ! CreateIterResultObject(value, F.[[Done]]).
-    return IteratorObject::createIterResultObject(state, value, F->m_done);
-}
-
-static Value asyncFromSyncIteratorValueUnwrap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return asyncFromSyncIteratorValueUnwrapLogic(state, (ScriptAsyncFromSyncIteratorHelperFunctionObject*)state.resolveCallee(), argv[0]);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-asyncfromsynciteratorcontinuation
-static Value asyncFromSyncIteratorContinuation(ExecutionState& state, Object* result, PromiseReaction::Capability promiseCapability)
-{
-    // Let done be IteratorComplete(result).
-    bool done;
-    try {
-        done = IteratorObject::iteratorComplete(state, result);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(done, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-    // Let value be IteratorValue(result).
-    Value value;
-    try {
-        value = IteratorObject::iteratorValue(state, result);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(value, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-    // Let valueWrapper be ? PromiseResolve(%Promise%, « value »).
-    PromiseObject* valueWrapper = nullptr;
-    try {
-        valueWrapper = PromiseObject::promiseResolve(state, state.context()->globalObject()->promise(), value)->asPromiseObject();
-    } catch (const Value& thrownValue) {
-        // * added step from 2020 (esid: language/statements/for-await-of/async-from-sync-iterator-continuation-abrupt-completion-get-constructor.js)
-        // IfAbruptRejectPromise(valueWrapper, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-
-    // Let steps be the algorithm steps defined in Async-from-Sync Iterator Value Unwrap Functions.
-    // Let onFulfilled be CreateBuiltinFunction(steps, « [[Done]] »).
-    // Set onFulfilled.[[Done]] to done.
-    auto onFulfilled = new ScriptAsyncFromSyncIteratorHelperFunctionObject(state, NativeFunctionInfo(AtomicString(), asyncFromSyncIteratorValueUnwrap, 1), done);
-    // Perform ! PerformPromiseThen(valueWrapper, onFulfilled, undefined, promiseCapability).
-    valueWrapper->then(state, onFulfilled, Value(), promiseCapability);
-    // Return promiseCapability.[[Promise]].
-    return promiseCapability.m_promise;
-}
-
-static Value builtinAsyncFromSyncIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.next
-    // Let O be the this value.
-    Value& O = thisValue;
-    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
-    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
-    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
-    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
-        // Let invalidIteratorError be a newly created TypeError object.
-        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-    // Let syncIteratorRecord be O.[[SyncIteratorRecord]].
-    auto syncIteratorRecord = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord();
-    Object* result;
-    try {
-        // Let result be IteratorNext(syncIteratorRecord, value).
-        result = IteratorObject::iteratorNext(state, syncIteratorRecord, argv[0]);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(result, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
-    return asyncFromSyncIteratorContinuation(state, result, promiseCapability);
-}
-
-static Value builtinAsyncFromSyncIteratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.return
-    Value value = argv[0];
-    // Let O be the this value.
-    Value& O = thisValue;
-    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
-    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
-    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
-    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
-        // Let invalidIteratorError be a newly created TypeError object.
-        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-    // Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
-    Object* syncIterator = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord()->m_iterator;
-    // Let return be GetMethod(syncIterator, "return").
-    Value returnVariable;
-    try {
-        returnVariable = Object::getMethod(state, syncIterator, state.context()->staticStrings().stringReturn);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(return, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-
-    // If return is undefined, then
-    if (returnVariable.isUndefined()) {
-        // Let iterResult be ! CreateIterResultObject(value, true).
-        Value iterResult = IteratorObject::createIterResultObject(state, value, true);
-        // Perform ! Call(promiseCapability.[[Resolve]], undefined, « iterResult »).
-        Object::call(state, promiseCapability.m_resolveFunction, Value(), 1, &iterResult);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let result be Call(return, syncIterator, « value »).
-    Value result;
-    try {
-        result = Object::call(state, returnVariable, syncIterator, 1, &value);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(return, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-
-    // If Type(result) is not Object, then
-    if (!result.isObject()) {
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
-        Value typeError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("result of iterator is not Object"));
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &typeError);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
-    return asyncFromSyncIteratorContinuation(state, result.asObject(), promiseCapability);
-}
-
-static Value builtinAsyncFromSyncIteratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.throw
-    Value value = argv[0];
-    // Let O be the this value.
-    Value& O = thisValue;
-    // Let promiseCapability be ! NewPromiseCapability(%Promise%).
-    auto promiseCapability = PromiseObject::newPromiseCapability(state, state.context()->globalObject()->promise());
-    // If Type(O) is not Object, or if O does not have a [[SyncIteratorRecord]] internal slot, then
-    if (!O.isObject() || !O.asObject()->isAsyncFromSyncIteratorObject()) {
-        // Let invalidIteratorError be a newly created TypeError object.
-        Value invalidIteratorError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("given this value is not Async-from-Sync Iterator"));
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « invalidIteratorError »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &invalidIteratorError);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let syncIterator be O.[[SyncIteratorRecord]].[[Iterator]].
-    Object* syncIterator = O.asObject()->asAsyncFromSyncIteratorObject()->syncIteratorRecord()->m_iterator;
-    // Let throw be GetMethod(syncIterator, "throw").
-    Value throwVariable;
-    try {
-        throwVariable = Object::getMethod(state, syncIterator, state.context()->staticStrings().stringThrow);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(return, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-
-    // If throw is undefined, then
-    if (throwVariable.isUndefined()) {
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &value);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let result be Call(throw, syncIterator, « value »).
-    Value result;
-    try {
-        result = Object::call(state, throwVariable, syncIterator, 1, &value);
-    } catch (const Value& thrownValue) {
-        // IfAbruptRejectPromise(result, promiseCapability).
-        Value argv = thrownValue;
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &argv);
-        return promiseCapability.m_promise;
-    }
-
-    // If Type(result) is not Object, then
-    if (!result.isObject()) {
-        // Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
-        Value typeError = ErrorObject::createError(state, ErrorObject::TypeError, String::fromASCII("result of iterator is not Object"));
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &typeError);
-        // Return promiseCapability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-    // Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability).
-    return asyncFromSyncIteratorContinuation(state, result.asObject(), promiseCapability);
-}
-
-void GlobalObject::installAsyncFromSyncIterator(ExecutionState& state)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%-object
-    m_asyncFromSyncIteratorPrototype = new Object(state, m_asyncIteratorPrototype);
-    m_asyncFromSyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_asyncFromSyncIteratorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                        ObjectPropertyDescriptor(String::fromASCII("Async-from-Sync Iterator"), ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinAsyncFromSyncIteratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
-                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinAsyncFromSyncIteratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_asyncFromSyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
-                                                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinAsyncFromSyncIteratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncFunction.cpp
deleted file mode 100644 (file)
index 895c680..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "GeneratorObject.h"
-#include "NativeFunctionObject.h"
-#include "runtime/ScriptAsyncFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinAsyncFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
-    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
-    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, false, true, false);
-
-    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->asyncFunctionPrototype();
-    });
-
-    return new ScriptAsyncFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
-}
-
-void GlobalObject::installAsyncFunction(ExecutionState& state)
-{
-    m_asyncFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncFunction, builtinAsyncFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_asyncFunction->setGlobalIntrinsicObject(state);
-    m_asyncFunction->setPrototype(state, m_function);
-
-    m_asyncFunctionPrototype = new Object(state, m_functionPrototype);
-    m_asyncFunctionPrototype->setGlobalIntrinsicObject(state, true);
-    m_asyncFunction->setFunctionPrototype(state, m_asyncFunctionPrototype);
-
-    m_asyncFunctionPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
-                                                ObjectPropertyDescriptor(m_asyncFunction, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_asyncFunctionPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                ObjectPropertyDescriptor(state.context()->staticStrings().AsyncFunction.string(), ObjectPropertyDescriptor::ConfigurablePresent));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncGeneratorFunction.cpp
deleted file mode 100644 (file)
index e5f46d8..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "runtime/ScriptAsyncGeneratorFunctionObject.h"
-#include "runtime/AsyncGeneratorObject.h"
-#include "runtime/NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinAsyncGeneratorFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
-    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
-    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, true, true, false);
-
-    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->asyncGenerator();
-    });
-
-    return new ScriptAsyncGeneratorFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
-}
-
-static Value builtinAsyncGeneratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Next, argv[0]);
-}
-
-static Value builtinAsyncGeneratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Return, argv[0]);
-}
-
-static Value builtinAsyncGeneratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Throw, argv[0]);
-}
-
-void GlobalObject::installAsyncGeneratorFunction(ExecutionState& state)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asyncgeneratorfunction
-    m_asyncGeneratorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncGeneratorFunction, builtinAsyncGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_asyncGeneratorFunction->setGlobalIntrinsicObject(state);
-    m_asyncGeneratorFunction->setPrototype(state, m_function);
-
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-asyncgeneratorfunction-prototype
-    m_asyncGenerator = new Object(state, m_functionPrototype);
-    m_asyncGenerator->setGlobalIntrinsicObject(state, true);
-
-    m_asyncGeneratorFunction->setFunctionPrototype(state, m_asyncGenerator);
-
-    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
-                                        ObjectPropertyDescriptor(m_asyncGeneratorFunction, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                        ObjectPropertyDescriptor(state.context()->staticStrings().AsyncGeneratorFunction.string(), ObjectPropertyDescriptor::ConfigurablePresent));
-
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-properties-of-asyncgenerator-prototype
-    m_asyncGeneratorPrototype = new Object(state, m_asyncIteratorPrototype);
-    m_asyncGeneratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_asyncGenerator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().prototype), ObjectPropertyDescriptor(m_asyncGeneratorPrototype, ObjectPropertyDescriptor::ConfigurablePresent));
-    m_asyncGeneratorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_asyncGenerator, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinAsyncGeneratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
-                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinAsyncGeneratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
-                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinAsyncGeneratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_asyncGeneratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                                ObjectPropertyDescriptor(Value(state.context()->staticStrings().AsyncGenerator.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAsyncIterator.cpp
deleted file mode 100644 (file)
index 4f253ac..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "runtime/NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinAsyncIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return thisValue;
-}
-
-void GlobalObject::installAsyncIterator(ExecutionState& state)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-object
-    m_asyncIteratorPrototype = new Object(state);
-    m_asyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asynciteratorprototype-asynciterator
-    m_asyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().asyncIterator),
-                                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.asyncIterator]")), builtinAsyncIteratorIterator, 0, NativeFunctionInfo::Strict)),
-                                                                                        (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinAtomics.cpp
deleted file mode 100644 (file)
index 6e85140..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#if defined(ENABLE_THREADING)
-
-#include "Escargot.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "TypedArrayObject.h"
-#include "TypedArrayInlines.h"
-#include "SharedArrayBufferObject.h"
-#include "CheckedArithmetic.h"
-
-namespace Escargot {
-
-enum class AtomicBinaryOps : uint8_t {
-    ADD,
-    AND,
-    EXCH,
-    OR,
-    SUB,
-    XOR,
-};
-
-static Value atomicIntegerOperations(ExecutionState& state, int32_t lnum, int32_t rnum, AtomicBinaryOps op)
-{
-    int32_t result = 0;
-    bool passed = true;
-
-    switch (op) {
-    case AtomicBinaryOps::ADD:
-        passed = ArithmeticOperations<int32_t, int32_t, int32_t>::add(lnum, rnum, result);
-        break;
-    case AtomicBinaryOps::AND:
-        result = lnum & rnum;
-        break;
-    case AtomicBinaryOps::EXCH:
-        result = rnum;
-        break;
-    case AtomicBinaryOps::OR:
-        result = lnum | rnum;
-        break;
-    case AtomicBinaryOps::SUB:
-        passed = ArithmeticOperations<int32_t, int32_t, int32_t>::sub(lnum, rnum, result);
-        break;
-    case AtomicBinaryOps::XOR:
-        result = lnum ^ rnum;
-        break;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        break;
-    };
-
-    if (LIKELY(passed)) {
-        return Value(result);
-    }
-
-    ASSERT(op == AtomicBinaryOps::ADD || op == AtomicBinaryOps::SUB);
-    if (op == AtomicBinaryOps::ADD) {
-        return Value(Value::EncodeAsDouble, static_cast<double>(lnum) + static_cast<double>(rnum));
-    }
-    return Value(Value::EncodeAsDouble, static_cast<double>(lnum) - static_cast<double>(rnum));
-}
-
-static Value atomicNumberOperations(ExecutionState& state, double lnum, double rnum, AtomicBinaryOps op)
-{
-    double result = 0;
-
-    switch (op) {
-    case AtomicBinaryOps::ADD:
-        result = lnum + rnum;
-        break;
-    case AtomicBinaryOps::AND:
-        result = Value(lnum).toInt32(state) & Value(rnum).toInt32(state);
-        break;
-    case AtomicBinaryOps::EXCH:
-        result = rnum;
-        break;
-    case AtomicBinaryOps::OR:
-        result = Value(lnum).toInt32(state) | Value(rnum).toInt32(state);
-        break;
-    case AtomicBinaryOps::SUB:
-        result = lnum - rnum;
-        break;
-    case AtomicBinaryOps::XOR:
-        result = Value(lnum).toInt32(state) ^ Value(rnum).toInt32(state);
-        break;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        break;
-    };
-
-    return Value(result);
-}
-
-static Value atomicBigIntOperations(ExecutionState& state, BigInt* lnum, BigInt* rnum, AtomicBinaryOps op)
-{
-    switch (op) {
-    case AtomicBinaryOps::ADD:
-        return lnum->addition(state, rnum);
-    case AtomicBinaryOps::AND:
-        return lnum->bitwiseAnd(state, rnum);
-    case AtomicBinaryOps::EXCH:
-        return rnum;
-    case AtomicBinaryOps::OR:
-        return lnum->bitwiseOr(state, rnum);
-    case AtomicBinaryOps::SUB:
-        return lnum->subtraction(state, rnum);
-    case AtomicBinaryOps::XOR:
-        return lnum->bitwiseXor(state, rnum);
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-        return Value();
-    };
-}
-
-static ArrayBufferObject* validateIntegerTypedArray(ExecutionState& state, Value typedArray, bool waitable = false)
-{
-    ArrayBufferObject* buffer = TypedArrayObject::validateTypedArray(state, typedArray);
-    TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject();
-
-    if (waitable) {
-        if ((TA->typedArrayType() != TypedArrayType::Int32) && (TA->typedArrayType() != TypedArrayType::BigInt64)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-        }
-    } else if ((TA->typedArrayType() == TypedArrayType::Uint8Clamped) || (TA->typedArrayType() == TypedArrayType::Float32) || (TA->typedArrayType() == TypedArrayType::Float64)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-    }
-
-    return buffer;
-}
-
-static size_t validateAtomicAccess(ExecutionState& state, TypedArrayObject* typedArray, Value index)
-{
-    uint64_t accessIndex = index.toIndex(state);
-    size_t length = typedArray->arrayLength();
-    if (UNLIKELY(accessIndex == Value::InvalidIndexValue || accessIndex >= (uint64_t)length)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::GlobalObject_RangeError);
-    }
-
-    ASSERT(accessIndex < std::numeric_limits<size_t>::max());
-    size_t elementSize = typedArray->elementSize();
-    size_t offset = typedArray->byteOffset();
-    return (static_cast<size_t>(accessIndex) * elementSize) + offset;
-}
-
-static Value getModifySetValueInBuffer(ExecutionState& state, ArrayBufferObject* buffer, size_t indexedPosition, TypedArrayType type, Value v2, AtomicBinaryOps op)
-{
-    size_t elemSize = TypedArrayHelper::elementSize(type);
-    ASSERT(indexedPosition + elemSize <= buffer->byteLength());
-
-    uint8_t* rawStart = const_cast<uint8_t*>(buffer->data()) + indexedPosition;
-    Value rawBytesRead = TypedArrayHelper::rawBytesToNumber(state, type, rawStart);
-    Value v1 = rawBytesRead;
-    Value val;
-
-    if (v1.isInt32() && v2.isInt32()) {
-        val = atomicIntegerOperations(state, v1.asInt32(), v2.asInt32(), op);
-    } else if (v1.isNumber() && v2.isNumber()) {
-        val = atomicNumberOperations(state, v1.asNumber(), v2.asNumber(), op);
-    } else {
-        ASSERT(v1.isBigInt() && v2.isBigInt());
-        auto lnum = v1.asBigInt();
-        auto rnum = v2.asBigInt();
-        val = atomicBigIntOperations(state, lnum, rnum, op);
-    }
-
-    uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
-    TypedArrayHelper::numberToRawBytes(state, type, val, rawBytes);
-    memcpy(rawStart, rawBytes, elemSize);
-
-    return rawBytesRead;
-}
-
-static Value atomicReadModifyWrite(ExecutionState& state, Value typedArray, Value index, Value value, AtomicBinaryOps op)
-{
-    ArrayBufferObject* buffer = validateIntegerTypedArray(state, typedArray);
-    TypedArrayObject* TA = typedArray.asObject()->asTypedArrayObject();
-    size_t indexedPosition = validateAtomicAccess(state, TA, index);
-    TypedArrayType type = TA->typedArrayType();
-
-    Value v;
-    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
-        v = value.toBigInt(state);
-    } else {
-        v = Value(value.toInteger(state));
-    }
-
-    return getModifySetValueInBuffer(state, buffer, indexedPosition, type, v, op);
-}
-
-static Value builtinAtomicsAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::ADD);
-}
-
-static Value builtinAtomicsAnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::AND);
-}
-
-static Value builtinAtomicsCompareExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]);
-    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
-    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
-    TypedArrayType type = TA->typedArrayType();
-
-    Value expected;
-    Value replacement;
-    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
-        expected = argv[2].toBigInt(state);
-        replacement = argv[3].toBigInt(state);
-    } else {
-        expected = Value(argv[2].toInteger(state));
-        replacement = Value(argv[3].toInteger(state));
-    }
-
-    size_t elemSize = TypedArrayHelper::elementSize(type);
-    ASSERT(indexedPosition + elemSize <= buffer->byteLength());
-    uint8_t* expectedBytes = ALLOCA(8, uint8_t, state);
-    TypedArrayHelper::numberToRawBytes(state, type, expected, expectedBytes);
-
-    // TODO SharedArrayBuffer case
-    uint8_t* rawStart = const_cast<uint8_t*>(buffer->data()) + indexedPosition;
-    Value rawBytesRead = TypedArrayHelper::rawBytesToNumber(state, type, rawStart);
-
-    bool isByteListEqual = true;
-    for (size_t i = 0; i < elemSize; i++) {
-        if (rawStart[i] != expectedBytes[i]) {
-            isByteListEqual = false;
-            break;
-        }
-    }
-    if (isByteListEqual) {
-        uint8_t* replacementBytes = ALLOCA(8, uint8_t, state);
-        TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes);
-        memcpy(rawStart, replacementBytes, elemSize);
-    }
-
-    return rawBytesRead;
-}
-
-static Value builtinAtomicsExchange(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::EXCH);
-}
-
-static Value builtinAtomicsLoad(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]);
-    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
-    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
-    TypedArrayType type = TA->typedArrayType();
-
-    return buffer->getValueFromBuffer(state, indexedPosition, type);
-}
-
-static Value builtinAtomicsOr(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::OR);
-}
-
-static Value builtinAtomicsStore(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ArrayBufferObject* buffer = validateIntegerTypedArray(state, argv[0]);
-    TypedArrayObject* TA = argv[0].asObject()->asTypedArrayObject();
-    size_t indexedPosition = validateAtomicAccess(state, TA, argv[1]);
-    TypedArrayType type = TA->typedArrayType();
-
-    Value value = argv[2];
-    Value v;
-    if (type == TypedArrayType::BigInt64 || type == TypedArrayType::BigUint64) {
-        v = value.toBigInt(state);
-    } else {
-        v = Value(value.toInteger(state));
-    }
-
-    buffer->setValueInBuffer(state, indexedPosition, type, v);
-    return v;
-}
-
-static Value builtinAtomicsSub(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::SUB);
-}
-
-static Value builtinAtomicsXor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::XOR);
-}
-
-void GlobalObject::installAtomics(ExecutionState& state)
-{
-    m_atomics = new Object(state);
-    m_atomics->setGlobalIntrinsicObject(state);
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                ObjectPropertyDescriptor(Value(state.context()->staticStrings().Atomics.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinAtomicsAdd, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringAnd),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringAnd, builtinAtomicsAnd, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().compareExchange),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().compareExchange, builtinAtomicsCompareExchange, 4, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().exchange),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().exchange, builtinAtomicsExchange, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().load),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().load, builtinAtomicsLoad, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringOr),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringOr, builtinAtomicsOr, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().store),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().store, builtinAtomicsStore, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sub),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sub, builtinAtomicsSub, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringXor),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringXor, builtinAtomicsXor, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Atomics),
-                      ObjectPropertyDescriptor(m_atomics, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
-
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBigInt.cpp
deleted file mode 100644 (file)
index 413ec19..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "BigIntObject.h"
-#include "NativeFunctionObject.h"
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#include "IntlNumberFormat.h"
-#endif
-
-namespace Escargot {
-
-static Value builtinBigIntConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is not undefined, throw a TypeError exception.
-    if (newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "illegal constructor BigInt");
-    }
-    // Let prim be ? ToPrimitive(value, hint Number).
-    Value prim = argv[0].toPrimitive(state, Value::PreferNumber);
-    // If Type(prim) is Number, return ? NumberToBigInt(prim).
-    if (prim.isNumber()) {
-        // NumberToBigInt(prim)
-        // If IsInteger(number) is false, throw a RangeError exception.
-        if (!prim.isInteger(state)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The value you input to BigInt constructor is not integer");
-        }
-        double numValue = prim.asNumber();
-        if ((numValue > (double)std::numeric_limits<int64_t>::max()) || (numValue < (double)std::numeric_limits<int64_t>::min())) {
-            // handle overflowed integer number
-            bf_t r;
-            bf_init(VMInstance::bfContext(), &r);
-            int ret = bf_set_float64(&r, numValue);
-            ASSERT(!ret);
-            ASSERT(bf_is_finite(&r));
-
-            return new BigInt(r);
-        }
-        // Return the BigInt value that represents the mathematical value of number.
-        return new BigInt((int64_t)numValue);
-    } else {
-        // Otherwise, return ? ToBigInt(value).
-        return argv[0].toBigInt(state);
-    }
-}
-
-static Value builtinBigIntAsUintN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let bits be ? ToIndex(bits).
-    auto bits = argv[0].toIndex(state);
-    if (bits == Value::InvalidIndexValue) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::CanNotConvertValueToIndex);
-    }
-    // Let bigint be ? ToBigInt(bigint).
-    BigInt* bigint = argv[1].toBigInt(state);
-    // Return a BigInt representing bigint modulo 2bits.
-    bf_t mask, r;
-    bf_init(VMInstance::bfContext(), &mask);
-    bf_init(VMInstance::bfContext(), &r);
-    bf_set_ui(&mask, 1);
-    bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
-    bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ);
-    bf_logic_and(&r, bigint->bf(), &mask);
-    bf_delete(&mask);
-
-    return new BigInt(r);
-}
-
-static Value builtinBigIntAsIntN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let bits be ? ToIndex(bits).
-    auto bits = argv[0].toIndex(state);
-    if (bits == Value::InvalidIndexValue) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::CanNotConvertValueToIndex);
-    }
-    // Let bigint be ? ToBigInt(bigint).
-    BigInt* bigint = argv[1].toBigInt(state);
-    // Return a BigInt representing bigint modulo 2bits.
-    bf_t mask, r;
-    bf_init(VMInstance::bfContext(), &mask);
-    bf_init(VMInstance::bfContext(), &r);
-    bf_set_ui(&mask, 1);
-    bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
-    bf_add_si(&mask, &mask, -1, BF_PREC_INF, BF_RNDZ);
-    bf_logic_and(&r, bigint->bf(), &mask);
-    if (bits != 0) {
-        bf_set_ui(&mask, 1);
-        bf_mul_2exp(&mask, bits - 1, BF_PREC_INF, BF_RNDZ);
-        if (bf_cmpu(&r, &mask) >= 0) {
-            bf_set_ui(&mask, 1);
-            bf_mul_2exp(&mask, bits, BF_PREC_INF, BF_RNDZ);
-            bf_sub(&r, &r, &mask, BF_PREC_INF, BF_RNDZ);
-        }
-    }
-    bf_delete(&mask);
-
-    return new BigInt(r);
-}
-
-// The abstract operation thisBigIntValue(value) performs the following steps:
-// If Type(value) is BigInt, return value.
-// If Type(value) is Object and value has a [[BigIntData]] internal slot, then
-// Assert: Type(value.[[BigIntData]]) is BigInt.
-// Return value.[[BigIntData]].
-// Throw a TypeError exception.
-#define RESOLVE_THIS_BINDING_TO_BIGINT(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                           \
-    BigInt* NAME = nullptr;                                                                                                                                                                                                                                  \
-    if (thisValue.isObject()) {                                                                                                                                                                                                                              \
-        if (!thisValue.asObject()->isBigIntObject()) {                                                                                                                                                                                                       \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-        }                                                                                                                                                                                                                                                    \
-        NAME = thisValue.asObject()->asBigIntObject()->primitiveValue();                                                                                                                                                                                     \
-    } else if (thisValue.isBigInt()) {                                                                                                                                                                                                                       \
-        NAME = thisValue.asBigInt();                                                                                                                                                                                                                         \
-    } else {                                                                                                                                                                                                                                                 \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);     \
-        return Value();                                                                                                                                                                                                                                      \
-    }
-
-static Value builtinBigIntToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_BIGINT(S, BigInt, toString);
-
-    double radix = 10;
-    if (argc > 0 && !argv[0].isUndefined()) {
-        radix = argv[0].toInteger(state);
-        if (radix < 2 || radix > 36) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_RadixInvalidRange);
-        }
-    }
-
-    return S->toString(radix);
-}
-
-static Value builtinBigIntValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_BIGINT(S, BigInt, valueOf);
-    return Value(S);
-}
-
-static Value builtinBigIntToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_BIGINT(thisObject, BigInt, toLocaleString);
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    Value locales = argc > 0 ? argv[0] : Value();
-    Value options = argc > 1 ? argv[1] : Value();
-    Object* numberFormat = IntlNumberFormat::create(state, state.context(), locales, options);
-    auto result = IntlNumberFormat::format(state, numberFormat, thisObject->toString());
-
-    return new UTF16String(result.data(), result.length());
-#else
-
-    ObjectGetResult toStrFuncGetResult = state.context()->globalObject()->bigIntProxyObject()->get(state, ObjectPropertyName(state.context()->staticStrings().toString));
-    if (toStrFuncGetResult.hasValue()) {
-        Value toStrFunc = toStrFuncGetResult.value(state, thisObject);
-        if (toStrFunc.isCallable()) {
-            // toLocaleString() ignores the first argument, unlike toString()
-            return Object::call(state, toStrFunc, thisObject, 0, argv);
-        }
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().BigInt.string(), true, state.context()->staticStrings().toLocaleString.string(), ErrorObject::Messages::GlobalObject_ToLocaleStringNotCallable);
-    RELEASE_ASSERT_NOT_REACHED();
-    return Value();
-#endif
-}
-
-void GlobalObject::installBigInt(ExecutionState& state)
-{
-    m_bigInt = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().BigInt, builtinBigIntConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_bigInt->setGlobalIntrinsicObject(state);
-
-    m_bigInt->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().asUintN),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asUintN, builtinBigIntAsUintN, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigInt->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().asIntN),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asIntN, builtinBigIntAsIntN, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigIntPrototype = new Object(state);
-    m_bigIntPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigIntPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                        ObjectPropertyDescriptor(state.context()->staticStrings().BigInt.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinBigIntToString, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigIntPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinBigIntValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_bigIntPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinBigIntToLocaleString, 0, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    m_bigInt->setFunctionPrototype(state, m_bigIntPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().BigInt),
-                      ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinBoolean.cpp
deleted file mode 100644 (file)
index 468d941..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "BooleanObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinBooleanConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    bool primitiveVal = argv[0].toBoolean(state);
-    if (!newTarget.hasValue()) {
-        return Value(primitiveVal);
-    } else {
-        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-            return constructorRealm->globalObject()->booleanPrototype();
-        });
-        BooleanObject* boolObj = new BooleanObject(state, proto, primitiveVal);
-        return boolObj;
-    }
-}
-
-static Value builtinBooleanValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isBoolean()) {
-        return Value(thisValue);
-    } else if (thisValue.isObject() && thisValue.asObject()->isBooleanObject()) {
-        return Value(thisValue.asPointerValue()->asBooleanObject()->primitiveValue());
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotBoolean);
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-static Value builtinBooleanToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isBoolean()) {
-        return Value(thisValue.toString(state));
-    } else if (thisValue.isObject() && thisValue.asObject()->isBooleanObject()) {
-        return Value(thisValue.asPointerValue()->asBooleanObject()->primitiveValue()).toString(state);
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotBoolean);
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-void GlobalObject::installBoolean(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_boolean = new NativeFunctionObject(state, NativeFunctionInfo(strings->Boolean, builtinBooleanConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_boolean->setGlobalIntrinsicObject(state);
-
-    m_booleanPrototype = new BooleanObject(state, m_objectPrototype, false);
-    m_booleanPrototype->setGlobalIntrinsicObject(state, true);
-    m_booleanPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.3.3.2 Boolean.prototype.toString
-    m_booleanPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinBooleanToString, 0, NativeFunctionInfo::Strict)),
-                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $19.3.3.3 Boolean.prototype.valueOf
-    m_booleanPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinBooleanValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_boolean->setFunctionPrototype(state, m_booleanPrototype);
-
-    defineOwnProperty(state, ObjectPropertyName(strings->Boolean),
-                      ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDataView.cpp
deleted file mode 100644 (file)
index 40d5827..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2017-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "DataViewObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-#define FOR_EACH_DATAVIEW_TYPES(F) \
-    F(Float32)                     \
-    F(Float64)                     \
-    F(Int8)                        \
-    F(Int16)                       \
-    F(Int32)                       \
-    F(Uint8)                       \
-    F(Uint16)                      \
-    F(Uint32)                      \
-    F(BigInt64)                    \
-    F(BigUint64)
-
-static Value builtinDataViewConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-    if (!(argv[0].isObject() && argv[0].asPointerValue()->isArrayBufferObject())) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotArrayBufferObject);
-    }
-
-    ArrayBufferObject* buffer = argv[0].asObject()->asArrayBufferObject();
-    double byteOffset = 0;
-    if (argc >= 2) {
-        Value& val = argv[1];
-        byteOffset = val.toIndex(state);
-        if (byteOffset == Value::InvalidIndexValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-        }
-    }
-    if (buffer->isDetachedBuffer()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, "%s: ArrayBuffer is detached buffer");
-    }
-    double bufferByteLength = buffer->byteLength();
-
-    if (byteOffset > bufferByteLength) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-    }
-    double byteLength = bufferByteLength - byteOffset;
-
-    if (argc >= 3) {
-        Value& val = argv[2];
-        if (!val.isUndefined()) {
-            byteLength = val.toIndex(state);
-            if (byteOffset + byteLength > bufferByteLength || byteLength == Value::InvalidIndexValue) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-            }
-        }
-    }
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->dataViewPrototype();
-    });
-    ArrayBufferView* obj = new DataViewObject(state, proto);
-    obj->setBuffer(buffer, byteOffset, byteLength);
-
-    if (obj->buffer()->isDetachedBuffer()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_DetachedBuffer);
-    }
-
-    return obj;
-}
-
-#define DECLARE_DATAVIEW_GETTER(Name)                                                                                                    \
-    static Value builtinDataViewGet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                    \
-        RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, DataView, get##Name);                                                                 \
-        if (!(thisObject->isDataViewObject())) {                                                                                         \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(),            \
-                                           true, state.context()->staticStrings().get##Name.string(),                                    \
-                                           ErrorObject::Messages::GlobalObject_ThisNotDataViewObject);                                   \
-        }                                                                                                                                \
-        if (argc < 2) {                                                                                                                  \
-            return thisObject->asDataViewObject()->getViewValue(state, argv[0], Value(false), TypedArrayType::Name);                     \
-        } else {                                                                                                                         \
-            return thisObject->asDataViewObject()->getViewValue(state, argv[0], argv[1], TypedArrayType::Name);                          \
-        }                                                                                                                                \
-    }
-
-#define DECLARE_DATAVIEW_SETTER(Name)                                                                                                    \
-    static Value builtinDataViewSet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                    \
-        RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, DataView, get##Name);                                                                 \
-        if (!(thisObject->isDataViewObject())) {                                                                                         \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().DataView.string(),            \
-                                           true, state.context()->staticStrings().set##Name.string(),                                    \
-                                           ErrorObject::Messages::GlobalObject_ThisNotDataViewObject);                                   \
-        }                                                                                                                                \
-        if (argc < 3) {                                                                                                                  \
-            return thisObject->asDataViewObject()->setViewValue(state, argv[0], Value(false), TypedArrayType::Name, argv[1]);            \
-        } else {                                                                                                                         \
-            return thisObject->asDataViewObject()->setViewValue(state, argv[0], argv[2], TypedArrayType::Name, argv[1]);                 \
-        }                                                                                                                                \
-    }
-
-FOR_EACH_DATAVIEW_TYPES(DECLARE_DATAVIEW_GETTER);
-FOR_EACH_DATAVIEW_TYPES(DECLARE_DATAVIEW_SETTER);
-
-static Value builtinDataViewBufferGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject())) {
-        ArrayBufferObject* buffer = thisValue.asObject()->asArrayBufferView()->buffer();
-        if (buffer) {
-            return Value(buffer);
-        }
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.buffer called on incompatible receiver");
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-static Value builtinDataViewByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject() && thisValue.asObject()->asDataViewObject()->buffer() && !thisValue.asObject()->asDataViewObject()->buffer()->isDetachedBuffer())) {
-        return Value(thisValue.asObject()->asArrayBufferView()->byteLength());
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.byteLength called on incompatible receiver");
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-static Value builtinDataViewByteOffsetGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (LIKELY(thisValue.isPointerValue() && thisValue.asPointerValue()->isDataViewObject() && thisValue.asObject()->asDataViewObject()->buffer() && !thisValue.asObject()->asDataViewObject()->buffer()->isDetachedBuffer())) {
-        return Value(thisValue.asObject()->asArrayBufferView()->byteOffset());
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "get DataView.prototype.byteOffset called on incompatible receiver");
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-void GlobalObject::installDataView(ExecutionState& state)
-{
-    m_dataView = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().DataView, builtinDataViewConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_dataView->setGlobalIntrinsicObject(state);
-
-    m_dataViewPrototype = new DataViewObject(state, m_objectPrototype);
-    m_dataViewPrototype->setGlobalIntrinsicObject(state, true);
-    m_dataView->setFunctionPrototype(state, m_dataViewPrototype);
-
-    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_dataViewPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                          ObjectPropertyDescriptor(Value(state.context()->staticStrings().DataView.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-#define DATAVIEW_DEFINE_GETTER(Name)                                                                                                                                                                                          \
-    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##Name),                                                                                                             \
-                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get##Name, builtinDataViewGet##Name, 1, NativeFunctionInfo::Strict)), \
-                                                                    (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-#define DATAVIEW_DEFINE_SETTER(Name)                                                                                                                                                                                          \
-    m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().set##Name),                                                                                                             \
-                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set##Name, builtinDataViewSet##Name, 2, NativeFunctionInfo::Strict)), \
-                                                                    (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    FOR_EACH_DATAVIEW_TYPES(DATAVIEW_DEFINE_GETTER);
-    FOR_EACH_DATAVIEW_TYPES(DATAVIEW_DEFINE_SETTER);
-
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getBuffer, builtinDataViewBufferGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor bufferDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->buffer), bufferDesc);
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinDataViewByteLengthGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteOffset, builtinDataViewByteOffsetGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor byteOffsetDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteOffset), byteOffsetDesc);
-    }
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().DataView),
-                      ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinDate.cpp
deleted file mode 100644 (file)
index 9c0bf02..0000000
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "DateObject.h"
-#include "ErrorObject.h"
-#include "NativeFunctionObject.h"
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#include "IntlDateTimeFormat.h"
-#endif
-
-namespace Escargot {
-
-#define FOR_EACH_DATE_VALUES(F)                     \
-    /* Name, DateSetterTypr, Setter length, UTC? */ \
-    F(Milliseconds, Time, 1, false)                 \
-    F(UTCMilliseconds, Time, 1, true)               \
-    F(Seconds, Time, 2, false)                      \
-    F(UTCSeconds, Time, 2, true)                    \
-    F(Minutes, Time, 3, false)                      \
-    F(UTCMinutes, Time, 3, true)                    \
-    F(Hours, Time, 4, false)                        \
-    F(UTCHours, Time, 4, true)                      \
-    F(Date, Day, 1, false)                          \
-    F(UTCDate, Day, 1, true)                        \
-    F(Month, Day, 2, false)                         \
-    F(UTCMonth, Day, 2, true)                       \
-    F(FullYear, Day, 3, false)                      \
-    F(UTCFullYear, Day, 3, true)
-
-
-bool isInValidRange(double year, double month, double date, double hour, double minute, double second, double millisecond)
-{
-    if (std::isnan(year) || std::isnan(month) || std::isnan(date) || std::isnan(hour) || std::isnan(minute) || std::isnan(second) || std::isnan(millisecond)) {
-        return false;
-    }
-    if (std::isinf(year) || std::isinf(month) || std::isinf(date) || std::isinf(hour) || std::isinf(minute) || std::isinf(second) || std::isinf(millisecond)) {
-        return false;
-    }
-
-    int32_t max32 = std::numeric_limits<int32_t>::max();
-    int64_t max64 = std::numeric_limits<int64_t>::max();
-    if (std::abs(year) > max32 || std::abs(month) > max32 || std::abs(date) > max32
-        || std::abs(hour) > max32 || std::abs(minute) > max32 || std::abs(second) > max64 || std::abs(millisecond) > max64) {
-        return false;
-    }
-    return true;
-}
-
-static Value builtinDateConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        DateObject d(state);
-        d.setTimeValue(DateObject::currentTime());
-        return d.toFullString(state);
-    } else {
-        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-            return constructorRealm->globalObject()->datePrototype();
-        });
-        DateObject* thisObject = new DateObject(state, proto);
-
-        if (argc == 0) {
-            thisObject->setTimeValue(DateObject::currentTime());
-        } else if (argc == 1) {
-            // https://www.ecma-international.org/ecma-262/6.0/#sec-date-value
-            Value v = argv[0];
-            // If Type(value) is Object and value has a [[DateValue]] internal slot, then
-            if (v.isObject() && v.asObject()->isDateObject()) {
-                // Let tv be thisTimeValue(value).
-                thisObject->setTimeValue(v.asObject()->asDateObject()->primitiveValue());
-                // Else
-            } else {
-                // Let v be ToPrimitive(value).
-                v = v.toPrimitive(state);
-                // If Type(v) is String, then
-                if (v.isString()) {
-                    thisObject->setTimeValue(state, v);
-                } else {
-                    // Let tv be ToNumber(v).
-                    double V = v.toNumber(state);
-                    thisObject->setTimeValue(DateObject::timeClip(state, V));
-                }
-            }
-        } else {
-            // https://www.ecma-international.org/ecma-262/6.0/#sec-date-year-month-date-hours-minutes-seconds-ms
-            // Assert: numberOfArgs ≥ 2.
-            ASSERT(argc > 1);
-            double args[7] = { 0, 0, 1, 0, 0, 0, 0 }; // default value of year, month, date, hour, minute, second, millisecond
-            argc = (argc > 7) ? 7 : argc; // trim arguments so that they don't corrupt stack
-            for (size_t i = 0; i < argc; i++) {
-                args[i] = argv[i].toNumber(state);
-            }
-            double year = args[0];
-            double month = args[1];
-            double date = args[2];
-            double hour = args[3];
-            double minute = args[4];
-            double second = args[5];
-            double millisecond = args[6];
-            if ((int)year >= 0 && (int)year <= 99) {
-                year += 1900;
-            }
-            if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
-                thisObject->setTimeValueAsNaN();
-            } else {
-                thisObject->setTimeValue(state, (int)year, (int)month, (int)date, (int)hour, (int)minute, second, millisecond);
-            }
-        }
-        return thisObject;
-    }
-}
-
-static Value builtinDateNow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return Value(DateObject::currentTime());
-}
-
-static Value builtinDateParse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value str = argv[0].toPrimitive(state, Value::PreferString);
-    if (str.isString()) {
-        DateObject d(state);
-        d.setTimeValue(state, str);
-        return Value(d.primitiveValue());
-    }
-    return Value(std::numeric_limits<double>::quiet_NaN());
-}
-
-static Value builtinDateUTC(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    DateObject d(state);
-    double args[7] = { std::numeric_limits<double>::quiet_NaN(), 0, 1, 0, 0, 0, 0 }; // default value of year, month, date, hour, minute, second, millisecond
-    argc = (argc > 7) ? 7 : argc; // trim arguments so that they don't corrupt stack
-    for (size_t i = 0; i < argc; i++) {
-        args[i] = argv[i].toNumber(state);
-    }
-    double year = args[0];
-    double month = args[1];
-    double date = args[2];
-    double hour = args[3];
-    double minute = args[4];
-    double second = args[5];
-    double millisecond = args[6];
-
-    if (!std::isnan(year)) {
-        int yi = (int)year;
-        if (yi >= 0 && yi <= 99) {
-            yi += 1900;
-            year = yi;
-        }
-    }
-
-    if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
-        d.setTimeValueAsNaN();
-    } else {
-        d.setTimeValue(state, year, month, date, hour, minute, second, millisecond, false);
-    }
-    return Value(d.primitiveValue());
-}
-
-#define RESOLVE_THIS_BINDING_TO_DATE(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                              \
-    if (!thisValue.isObject() || !thisValue.asObject()->isDateObject()) {                                                                                                                                                                     \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_ThisNotDateObject); \
-    }                                                                                                                                                                                                                                         \
-    DateObject* NAME = thisValue.asObject()->asDateObject();
-
-static Value builtinDateGetTime(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getTime);
-    return Value(thisObject->primitiveValue());
-}
-
-static Value builtinDateValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, valueOf);
-    double val = thisObject->primitiveValue();
-    return Value(val);
-}
-
-static Value builtinDateToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-    return thisObject->toFullString(state);
-}
-
-static Value builtinDateToDateString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-    return thisObject->toDateString(state);
-}
-
-static Value builtinDateToTimeString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-    return thisObject->toTimeString(state);
-}
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#define INTL_DATE_TIME_FORMAT_FORMAT(REQUIRED, DEFUALT)                                                                                   \
-    double x = thisObject->primitiveValue();                                                                                              \
-    if (std::isnan(x)) {                                                                                                                  \
-        return new ASCIIString("Invalid Date");                                                                                           \
-    }                                                                                                                                     \
-    Value locales, options;                                                                                                               \
-    if (argc >= 1) {                                                                                                                      \
-        locales = argv[0];                                                                                                                \
-    }                                                                                                                                     \
-    if (argc >= 2) {                                                                                                                      \
-        options = argv[1];                                                                                                                \
-    }                                                                                                                                     \
-    auto dateTimeOption = IntlDateTimeFormat::toDateTimeOptions(state, options, String::fromASCII(REQUIRED), String::fromASCII(DEFUALT)); \
-    Object* dateFormat = IntlDateTimeFormat::create(state, state.context(), locales, dateTimeOption);                                     \
-    auto result = IntlDateTimeFormat::format(state, dateFormat, x);                                                                       \
-    return new UTF16String(result.data(), result.length());
-#endif
-
-static Value builtinDateToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    INTL_DATE_TIME_FORMAT_FORMAT("any", "all")
-#else
-    return thisObject->toLocaleFullString(state);
-#endif
-}
-
-static Value builtinDateToLocaleDateString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    INTL_DATE_TIME_FORMAT_FORMAT("date", "date")
-#else
-    return thisObject->toLocaleDateString(state);
-#endif
-}
-
-static Value builtinDateToLocaleTimeString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toString);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    INTL_DATE_TIME_FORMAT_FORMAT("time", "time")
-#else
-    return thisObject->toLocaleTimeString(state);
-#endif
-}
-
-static Value builtinDateToUTCString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toUTCString);
-    return thisObject->toUTCString(state, state.context()->staticStrings().toUTCString.string());
-}
-
-static Value builtinDateToISOString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, toISOString);
-    return thisObject->toISOString(state);
-}
-
-static Value builtinDateToJSON(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Date, toJSON);
-
-    Value tv = Value(thisObject).toPrimitive(state, Value::PreferNumber);
-    if (tv.isNumber() && (std::isnan(tv.asNumber()) || std::isinf(tv.asNumber()))) {
-        return Value(Value::Null);
-    }
-
-    Value isoFunc = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toISOString)).value(state, thisObject);
-    return Object::call(state, isoFunc, thisObject, 0, nullptr);
-}
-
-#define DECLARE_STATIC_DATE_GETTER(Name, unused1, unused2, unused3)                                                                  \
-    static Value builtinDateGet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                \
-        RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, get##Name);                                                                   \
-        if (!(thisObject->isValid()))                                                                                                \
-            return Value(std::numeric_limits<double>::quiet_NaN());                                                                  \
-        return Value(thisObject->get##Name(state));                                                                                  \
-    }
-
-FOR_EACH_DATE_VALUES(DECLARE_STATIC_DATE_GETTER);
-DECLARE_STATIC_DATE_GETTER(Day, -, -, -);
-DECLARE_STATIC_DATE_GETTER(UTCDay, -, -, -);
-
-enum DateSetterType : unsigned {
-    Time,
-    Day
-};
-
-static Value builtinDateSetHelper(ExecutionState& state, DateSetterType setterType, size_t length, bool utc, Value thisValue, size_t argc, Value* argv, const AtomicString& name)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, name);
-    DateObject* d = thisObject;
-
-    if (setterType == DateSetterType::Day && length == 3) {
-        // setFullYear, setUTCFullYear case
-        if (!(d->isValid())) {
-            d->setTimeValue(DateObject::timeClip(state, 0));
-            d->setTimeValue(d->getTimezoneOffset(state) * const_Date_msPerMinute);
-        }
-        ASSERT(d->isValid());
-    }
-
-    if (argc < 1) {
-        d->setTimeValueAsNaN();
-        return Value(d->primitiveValue());
-    }
-
-    double year = 0, month = 0, date = 0, hour = 0, minute = 0, second = 0, millisecond = 0;
-
-    if (d->isValid()) {
-        if (!utc) {
-            year = d->getFullYear(state);
-            month = d->getMonth(state);
-            date = d->getDate(state);
-
-            hour = d->getHours(state);
-            minute = d->getMinutes(state);
-            second = d->getSeconds(state);
-            millisecond = d->getMilliseconds(state);
-        } else {
-            year = d->getUTCFullYear(state);
-            month = d->getUTCMonth(state);
-            date = d->getUTCDate(state);
-
-            hour = d->getUTCHours(state);
-            minute = d->getUTCMinutes(state);
-            second = d->getUTCSeconds(state);
-            millisecond = d->getUTCMilliseconds(state);
-        }
-    }
-
-    bool convertToUTC = !utc;
-
-    switch (setterType) {
-    case DateSetterType::Day:
-        if ((length >= 3) && (argc > length - 3))
-            year = argv[length - 3].toNumber(state);
-        if ((length >= 2) && (argc > length - 2))
-            month = argv[length - 2].toNumber(state);
-        if ((length >= 1) && (argc > length - 1))
-            date = argv[length - 1].toNumber(state);
-        break;
-    case DateSetterType::Time:
-        if ((length >= 4) && (argc > length - 4))
-            hour = argv[length - 4].toNumber(state);
-        if ((length >= 3) && (argc > length - 3))
-            minute = argv[length - 3].toNumber(state);
-        if ((length >= 2) && (argc > length - 2))
-            second = argv[length - 2].toNumber(state);
-        if ((length >= 1) && (argc > length - 1))
-            millisecond = argv[length - 1].toNumber(state);
-        break;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-
-    if (UNLIKELY(!isInValidRange(year, month, date, hour, minute, second, millisecond))) {
-        d->setTimeValueAsNaN();
-    } else if (d->isValid()) {
-        d->setTimeValue(state, year, month, date, hour, minute, second, millisecond, convertToUTC);
-    }
-
-    return Value(d->primitiveValue());
-}
-
-#define DECLARE_STATIC_DATE_SETTER(Name, setterType, length, utc)                                                                                              \
-    static Value builtinDateSet##Name(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)                           \
-    {                                                                                                                                                          \
-        return Value(builtinDateSetHelper(state, DateSetterType::setterType, length, utc, thisValue, argc, argv, state.context()->staticStrings().set##Name)); \
-    }
-
-FOR_EACH_DATE_VALUES(DECLARE_STATIC_DATE_SETTER);
-
-static Value builtinDateSetTime(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, setTime);
-    if (argc > 0) {
-        thisObject->setTimeValue(DateObject::timeClip(state, argv[0].toNumber(state)));
-        return Value(thisObject->primitiveValue());
-    } else {
-        double value = std::numeric_limits<double>::quiet_NaN();
-        thisObject->setTimeValueAsNaN();
-        return Value(value);
-    }
-}
-
-static Value builtinDateGetYear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getYear);
-    if (!(thisObject->isValid())) {
-        return Value(std::numeric_limits<double>::quiet_NaN());
-    }
-    int ret = thisObject->getFullYear(state) - 1900;
-    return Value(ret);
-}
-
-static Value builtinDateSetYear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, setYear);
-    DateObject* d = thisObject;
-
-    if (!(d->isValid())) {
-        d->setTimeValue(DateObject::timeClip(state, 0));
-        d->setTimeValue(d->getTimezoneOffset(state) * const_Date_msPerMinute);
-    }
-    ASSERT(d->isValid());
-
-    if (argc < 1) {
-        d->setTimeValueAsNaN();
-        return Value(d->primitiveValue());
-    }
-
-    double y;
-    int month, date, hour, minute, second, millisecond;
-
-    // Let y be ToNumber(year).
-    y = argv[0].toNumber(state);
-    // If y is NaN, set the [[DateValue]] internal slot of this Date object to NaN and return NaN.
-    if (std::isnan(y)) {
-        d->setTimeValueAsNaN();
-        return Value(d->primitiveValue());
-    }
-
-    month = d->getMonth(state);
-    date = d->getDate(state);
-    hour = d->getHours(state);
-    minute = d->getMinutes(state);
-    second = d->getSeconds(state);
-    millisecond = d->getMilliseconds(state);
-
-    double yyyy;
-    double yAsInteger = Value(y).toInteger(state);
-    // If y is not NaN and 0 ≤ ToInteger(y) ≤ 99, let yyyy be ToInteger(y) + 1900.
-    if (0 <= yAsInteger && yAsInteger <= 99) {
-        yyyy = 1900 + yAsInteger;
-    } else {
-        // Else, let yyyy be y.
-        yyyy = y;
-    }
-
-    if (d->isValid()) {
-        d->setTimeValue(state, yyyy, month, date, hour, minute, second, millisecond);
-    }
-
-    return Value(d->primitiveValue());
-}
-
-static Value builtinDateGetTimezoneOffset(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_DATE(thisObject, Date, getTimezoneOffset);
-    if (!(thisObject->isValid()))
-        return Value(std::numeric_limits<double>::quiet_NaN());
-    return Value(thisObject->getTimezoneOffset(state));
-}
-
-static Value builtinDateToPrimitive(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the this value.
-    Value O = thisValue;
-    // If Type(O) is not Object, throw a TypeError exception.
-    if (!O.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Date.string(), true,
-                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    bool tryFirstIsString = false;
-    // If hint is the String value "string" or the String value "default", then
-    if (argv[0].isString() && (argv[0].asString()->equals("string") || argv[0].asString()->equals("default"))) {
-        // Let tryFirst be "string".
-        tryFirstIsString = true;
-    } else if (argv[0].isString() && argv[0].asString()->equals("number")) {
-        // Else if hint is the String value "number", then
-        // Let tryFirst be "number".
-        tryFirstIsString = false;
-    } else {
-        // Else, throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Date.string(), true,
-                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-    }
-    // Return ? OrdinaryToPrimitive(O, tryFirst).
-    if (tryFirstIsString) {
-        return O.ordinaryToPrimitive(state, Value::PreferString);
-    } else {
-        return O.ordinaryToPrimitive(state, Value::PreferNumber);
-    }
-}
-
-void GlobalObject::installDate(ExecutionState& state)
-{
-    m_date = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Date, builtinDateConstructor, 7), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_date->setGlobalIntrinsicObject(state);
-
-    m_datePrototype = new Object(state);
-    m_datePrototype->setGlobalIntrinsicObject(state, true);
-
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().now),
-                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().now, builtinDateNow, 0, NativeFunctionInfo::Strict)),
-                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parse),
-                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().parse, builtinDateParse, 1, NativeFunctionInfo::Strict)),
-                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_date->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().UTC),
-                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().UTC, builtinDateUTC, 7, NativeFunctionInfo::Strict)),
-                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getTime),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getTime, builtinDateGetTime, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().setTime),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setTime, builtinDateSetTime, 1, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinDateValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinDateToString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toDateString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toDateString, builtinDateToDateString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toTimeString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toTimeString, builtinDateToTimeString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleString, builtinDateToLocaleString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleDateString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleDateString, builtinDateToLocaleDateString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toLocaleTimeString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toLocaleTimeString, builtinDateToLocaleTimeString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toISOString),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toISOString, builtinDateToISOString, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toJSON),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toJSON, builtinDateToJSON, 1, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    FunctionObject* toUTCString = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toUTCString, builtinDateToUTCString, 0, NativeFunctionInfo::Strict));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toUTCString),
-                                       ObjectPropertyDescriptor(toUTCString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toGMTString),
-                                       ObjectPropertyDescriptor(toUTCString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getYear),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getYear, builtinDateGetYear, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().setYear),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setYear, builtinDateSetYear, 1, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getTimezoneOffset),
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getTimezoneOffset, builtinDateGetTimezoneOffset, 0, NativeFunctionInfo::Strict)),
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_datePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toPrimitive)),
-                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.toPrimitive]")), builtinDateToPrimitive, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-#define DATE_DEFINE_GETTER(dname, unused1, unused2, unused3)                                                                                                                                                            \
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##dname),                                                                                                          \
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get##dname, builtinDateGet##dname, 0, NativeFunctionInfo::Strict)), \
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    FOR_EACH_DATE_VALUES(DATE_DEFINE_GETTER);
-    DATE_DEFINE_GETTER(Day, -, -, -);
-    DATE_DEFINE_GETTER(UTCDay, -, -, -);
-
-#define DATE_DEFINE_SETTER(dname, unused1, length, unused3)                                                                                                                                                                  \
-    m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().set##dname),                                                                                                               \
-                                       ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set##dname, builtinDateSet##dname, length, NativeFunctionInfo::Strict)), \
-                                                                (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    FOR_EACH_DATE_VALUES(DATE_DEFINE_SETTER);
-
-    m_date->setFunctionPrototype(state, m_datePrototype);
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Date),
-                      ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinError.cpp
deleted file mode 100644 (file)
index bc8f844..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "ErrorObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->errorPrototype();
-    });
-    ErrorObject* obj = new ErrorObject(state, proto, String::emptyString);
-
-    Value message = argv[0];
-    if (!message.isUndefined()) {
-        obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
-                                                            ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
-    }
-    return obj;
-}
-
-#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName)                                                                                                                                                                                                              \
-    static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)                                                                                                                  \
-    {                                                                                                                                                                                                                                                                 \
-        if (!newTarget.hasValue()) {                                                                                                                                                                                                                                  \
-            newTarget = state.resolveCallee();                                                                                                                                                                                                                        \
-        }                                                                                                                                                                                                                                                             \
-        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {                                                                                                               \
-            return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype();                                                                                                                                                                            \
-        });                                                                                                                                                                                                                                                           \
-        ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString);                                                                                                                                                                             \
-        Value message = argv[0];                                                                                                                                                                                                                                      \
-        if (!message.isUndefined()) {                                                                                                                                                                                                                                 \
-            obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,                                                                                                                                                      \
-                                                                ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
-        }                                                                                                                                                                                                                                                             \
-        return obj;                                                                                                                                                                                                                                                   \
-    }
-
-DEFINE_ERROR_CTOR(Reference, reference);
-DEFINE_ERROR_CTOR(Type, type);
-DEFINE_ERROR_CTOR(Syntax, syntax);
-DEFINE_ERROR_CTOR(Range, range);
-DEFINE_ERROR_CTOR(URI, uri);
-DEFINE_ERROR_CTOR(Eval, eval);
-
-static Value builtinAggregateErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-    // Let O be ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->aggregateErrorPrototype();
-    });
-    ErrorObject* O = new AggregateErrorObject(state, proto, String::emptyString);
-    Value message = argv[1];
-    // If message is not undefined, then
-    if (!message.isUndefined()) {
-        // Let msg be ? ToString(message).
-        // Let msgDesc be the PropertyDescriptor { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
-        // Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
-        O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
-                                                          ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
-    }
-
-    // Let errorsList be ? IterableToList(errors).
-    auto errorsList = IteratorObject::iterableToList(state, argv[0]);
-    // Perform ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errorsList) }).
-    O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, String::fromASCII("errors")),
-                                                      ObjectPropertyDescriptor(Value(Object::createArrayFromList(state, errorsList.size(), errorsList.data())), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
-    // Return O.
-    return O;
-}
-
-static Value builtinErrorThrowTypeError(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "");
-    return Value();
-}
-
-static Value builtinErrorToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject())
-        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, state.context()->staticStrings().Error.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-
-    Object* o = thisValue.toObject(state);
-
-    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(o)) {
-        return String::emptyString;
-    }
-    ToStringRecursionPreventerItemAutoHolder holder(state, o);
-
-    Value name = o->get(state, state.context()->staticStrings().name).value(state, o);
-    String* nameStr;
-    if (name.isUndefined()) {
-        nameStr = state.context()->staticStrings().Error.string();
-    } else {
-        nameStr = name.toString(state);
-    }
-    Value message = o->get(state, state.context()->staticStrings().message).value(state, o);
-    String* messageStr;
-    if (message.isUndefined()) {
-        messageStr = String::emptyString;
-    } else {
-        messageStr = message.toString(state);
-    }
-
-    if (nameStr->length() == 0) {
-        return messageStr;
-    }
-
-    if (messageStr->length() == 0) {
-        return nameStr;
-    }
-
-    StringBuilder builder;
-    builder.appendString(nameStr);
-    builder.appendString(": ");
-    builder.appendString(messageStr);
-    return builder.finalize(&state);
-}
-
-void GlobalObject::installError(ExecutionState& state)
-{
-    m_error = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Error, builtinErrorConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_error->setGlobalIntrinsicObject(state);
-
-    m_errorPrototype = new Object(state);
-    m_errorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_error->setFunctionPrototype(state, m_errorPrototype);
-
-    m_errorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(state.context()->staticStrings().Error.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    auto errorToStringFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinErrorToString, 0, NativeFunctionInfo::Strict));
-    m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().toString, ObjectPropertyDescriptor(errorToStringFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.3
-    // 13.2.3 The [[ThrowTypeError]] Function Object
-    m_throwTypeError = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinErrorThrowTypeError, 0, NativeFunctionInfo::Strict));
-    m_throwTypeError->setGlobalIntrinsicObject(state, false);
-    m_throwTypeError->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().length),
-                                        ObjectPropertyDescriptor(Value(0), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
-    m_throwTypeError->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().name),
-                                        ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
-    m_throwTypeError->preventExtensions(state);
-
-    m_throwerGetterSetterData = new JSGetterSetter(m_throwTypeError, m_throwTypeError);
-
-#define DEFINE_ERROR(errorname, bname, length)                                                                                                                                                                                                                                                                                          \
-    m_##errorname##Error = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bname##Error, builtin##bname##ErrorConstructor, length), NativeFunctionObject::__ForBuiltinConstructor__);                                                                                                               \
-    m_##errorname##Error->setPrototype(state, m_error);                                                                                                                                                                                                                                                                                 \
-    m_##errorname##ErrorPrototype = new Object(state, m_errorPrototype);                                                                                                                                                                                                                                                                \
-    m_##errorname##ErrorPrototype->setGlobalIntrinsicObject(state, true);                                                                                                                                                                                                                                                               \
-    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().constructor, ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));                            \
-    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));                                 \
-    m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(state.context()->staticStrings().bname##Error.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
-    m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype);                                                                                                                                                                                                                                                   \
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error),                                                                                                                                                                                                                                         \
-                      ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
-
-    DEFINE_ERROR(reference, Reference, 1);
-    DEFINE_ERROR(type, Type, 1);
-    DEFINE_ERROR(syntax, Syntax, 1);
-    DEFINE_ERROR(range, Range, 1);
-    DEFINE_ERROR(uri, URI, 1);
-    DEFINE_ERROR(eval, Eval, 1);
-    DEFINE_ERROR(aggregate, Aggregate, 2);
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Error),
-                      ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFinalizationRegistry.cpp
deleted file mode 100644 (file)
index e58dd32..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "FinalizationRegistryObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-#define RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(NAME, BUILT_IN_METHOD)                                                                                                                                                                                               \
-    if (!thisValue.isObject() || !thisValue.asObject()->isFinalizationRegistryObject()) {                                                                                                                                                                                 \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().FinalizationRegistry.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                                     \
-    FinalizationRegistryObject* NAME = thisValue.asObject()->asFinalizationRegistryObject();
-
-static Value builtinFinalizationRegistryConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-    if (argc == 0 || !argv[0].isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "cleanup Callback is not callable");
-    }
-
-    // Let finalizationRegistry be ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistryPrototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->finalizationRegistryPrototype();
-    });
-
-    return new FinalizationRegistryObject(state, proto, argv[0].asObject(), state.resolveCallee()->getFunctionRealm(state));
-}
-
-static Value builtinfinalizationRegistryRegister(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, stringRegister);
-
-    if (argc == 0 || !argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target is not object");
-    }
-    if (argv[0] == argv[1]) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target and heldValue is the same");
-    }
-
-    Optional<Object*> unregisterToken;
-    if (argc >= 3) {
-        if (argv[2].isObject()) {
-            unregisterToken = argv[2].asObject();
-        } else if (!argv[2].isUndefined()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "unregisterToken is not undefined");
-        }
-    }
-    finalRegistry->setCell(state, argv[0].asObject(), argv[1], unregisterToken);
-    return Value();
-}
-
-static Value builtinfinalizationRegistryUnregister(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, unregister);
-    if (argc == 0 || !argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "unregisterToken is not object");
-    }
-    return Value(finalRegistry->deleteCell(state, argv[0].asObject()));
-}
-
-static Value builtinfinalizationRegistryCleanupSome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_FINALIZATIONREGISTRY(finalRegistry, cleanupSome);
-
-    // If callback is not undefined and IsCallable(callback) is false, throw a TypeError exception
-    Object* callback = nullptr;
-    if (argc && !argv[0].isUndefined()) {
-        if (!argv[0].isCallable()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "callback is not callable");
-        }
-        callback = argv[0].asObject();
-    }
-
-    finalRegistry->cleanupSome(state, callback);
-
-    return Value();
-}
-
-void GlobalObject::installFinalizationRegistry(ExecutionState& state)
-{
-    m_finalizationRegistry = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().FinalizationRegistry, builtinFinalizationRegistryConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_finalizationRegistry->setGlobalIntrinsicObject(state);
-
-    m_finalizationRegistryPrototype = new Object(state, m_objectPrototype);
-    m_finalizationRegistryPrototype->setGlobalIntrinsicObject(state, true);
-    m_finalizationRegistryPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                                      ObjectPropertyDescriptor(Value(state.context()->staticStrings().FinalizationRegistry.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // FinalizationRegistry.prototype.unregister
-    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().unregister),
-                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().unregister, builtinfinalizationRegistryUnregister, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // FinalizationRegistry.prototype.register
-    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringRegister),
-                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringRegister, builtinfinalizationRegistryRegister, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // https://github.com/tc39/proposal-cleanup-some
-    // FinalizationRegistry.prototype.cleanupSome
-    m_finalizationRegistryPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cleanupSome),
-                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cleanupSome, builtinfinalizationRegistryCleanupSome, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_finalizationRegistry->setFunctionPrototype(state, m_finalizationRegistryPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().FinalizationRegistry),
-                      ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::NonEnumerablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinFunction.cpp
deleted file mode 100644 (file)
index 0230f62..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "runtime/BoundFunctionObject.h"
-#include "runtime/ScriptFunctionObject.h"
-#include "runtime/ScriptClassConstructorFunctionObject.h"
-#include "parser/Lexer.h"
-
-namespace Escargot {
-
-static Value builtinFunctionEmptyFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return Value();
-}
-
-static Value builtinFunctionConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (newTarget.hasValue() && UNLIKELY((bool)state.context()->securityPolicyCheckCallback())) {
-        Value checkMSG = state.context()->securityPolicyCheckCallback()(state, false);
-        if (!checkMSG.isEmpty()) {
-            ASSERT(checkMSG.isString());
-            ErrorObject::throwBuiltinError(state, ErrorObject::Code::EvalError, checkMSG.asString());
-            return Value();
-        }
-    }
-
-    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
-    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
-    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, false, false, false);
-
-    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->functionPrototype();
-    });
-
-    ScriptFunctionObject* result = new ScriptFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment, true, false, false);
-
-    return result;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-function.prototype.tostring
-static Value builtinFunctionToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (LIKELY(thisValue.isObject())) {
-        Object* func = thisValue.asObject();
-
-        if (LIKELY(func->isFunctionObject())) {
-            FunctionObject* fn = func->asFunctionObject();
-
-            if (fn->isScriptClassConstructorFunctionObject()) {
-                return fn->asScriptFunctionObject()->asScriptClassConstructorFunctionObject()->classSourceCode();
-            } else {
-                StringBuilder builder;
-                if (fn->isScriptFunctionObject()) {
-                    StringView src = fn->asScriptFunctionObject()->interpretedCodeBlock()->src();
-                    size_t length = src.length();
-                    while (length > 0 && EscargotLexer::isWhiteSpaceOrLineTerminator(src[length - 1])) {
-                        length--;
-                    }
-                    builder.appendString(new StringView(src, 0, length));
-                } else {
-                    ASSERT(fn->isNativeFunctionObject());
-                    builder.appendString("function ");
-                    builder.appendString(fn->codeBlock()->functionName().string());
-                    builder.appendString("() { [native code] }");
-                }
-
-                return builder.finalize(&state);
-            }
-        }
-
-        if (func->isBoundFunctionObject() || func->isCallable()) {
-            StringBuilder builder;
-            builder.appendString("function () { [native code] }");
-            return builder.finalize(&state);
-        }
-    }
-
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
-    return Value();
-}
-
-static Value builtinFunctionApply(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
-    }
-    Value thisArg = argv[0];
-    Value argArray = argv[1];
-    size_t arrlen = 0;
-    Value* arguments = nullptr;
-    ValueVector argList;
-    if (argArray.isUndefinedOrNull()) {
-        // TODO
-    } else {
-        argList = Object::createListFromArrayLike(state, argArray);
-        arrlen = argList.size();
-        arguments = argList.data();
-    }
-
-    return Object::call(state, thisValue, thisArg, arrlen, arguments);
-}
-
-static Value builtinFunctionCall(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().apply.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
-    }
-    Value thisArg = argv[0];
-    size_t arrlen = argc > 0 ? argc - 1 : 0;
-    Value* arguments = ALLOCA(sizeof(Value) * arrlen, Value, state);
-    for (size_t i = 0; i < arrlen; i++) {
-        arguments[i] = argv[i + 1];
-    }
-
-    return Object::call(state, thisValue, thisArg, arrlen, arguments);
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.bind
-static Value builtinFunctionBind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If IsCallable(Target) is false, throw a TypeError exception.
-    if (!thisValue.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Function.string(), true, state.context()->staticStrings().bind.string(), ErrorObject::Messages::GlobalObject_ThisNotFunctionObject);
-    }
-
-    // Let Target be the this value.
-    Object* target = thisValue.asObject();
-
-    // Let args be a new (possibly empty) List consisting of all of the argument values provided after thisArg in order.
-    Value boundThis = argv[0];
-    size_t boundArgc = (argc > 0) ? argc - 1 : 0;
-    Value* boundArgv = (boundArgc > 0) ? argv + 1 : nullptr;
-    //BoundFunctionObject* F = new BoundFunctionObject(state, thisValue, boundThis, boundArgc, boundArgv);
-
-    // Let targetHasLength be HasOwnProperty(Target, "length").
-    bool targetHasLength = target->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().length));
-    double length = 0;
-    // If targetHasLength is true, then
-    if (targetHasLength) {
-        // Let targetLen be Get(Target, "length").
-        Value targetLen = target->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, target);
-        // If Type(targetLen) is not Number, let L be 0.
-        // Else Let targetLen be ToInteger(targetLen).
-        // Let L be the larger of 0 and the result of targetLen minus the number of elements of args.
-        if (targetLen.isNumber()) {
-            length = std::max(0.0, targetLen.toInteger(state) - boundArgc);
-        }
-    }
-
-    // F->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().length),
-    //                                    ObjectPropertyDescriptor(Value(length), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // Let targetName be Get(Target, "name").
-    Value targetName = target->get(state, ObjectPropertyName(state.context()->staticStrings().name)).value(state, target);
-    // If Type(targetName) is not String, let targetName be the empty string.
-    if (!targetName.isString()) {
-        targetName = String::emptyString;
-    }
-
-    StringBuilder builder;
-    builder.appendString("bound ");
-    builder.appendString(targetName.asString());
-    //F->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().name),
-    //                                    ObjectPropertyDescriptor(Value(builder.finalize(&state)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // Let F be BoundFunctionCreate(Target, thisArg, args).
-    // Let status be DefinePropertyOrThrow(F, "length", PropertyDescriptor {[[Value]]: L, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}).
-    // Perform SetFunctionName(F, targetName, "bound").
-    // Return F.
-    return new BoundFunctionObject(state, target, boundThis, boundArgc, boundArgv, Value(length), Value(builder.finalize(&state)));
-}
-
-static Value builtinFunctionHasInstanceOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        return Value(false);
-    }
-    return Value(thisValue.asObject()->hasInstance(state, argv[0]));
-}
-
-void GlobalObject::installFunction(ExecutionState& state)
-{
-    m_functionPrototype = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinFunctionEmptyFunction, 0, NativeFunctionInfo::Strict),
-                                                   NativeFunctionObject::__ForGlobalBuiltin__);
-    m_functionPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_function = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Function, builtinFunctionConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_function->setGlobalIntrinsicObject(state);
-    m_function->setFunctionPrototype(state, m_functionPrototype);
-
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().constructor),
-                                                          ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toString),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinFunctionToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_functionApply = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().apply, builtinFunctionApply, 2, NativeFunctionInfo::Strict));
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().apply),
-                                                          ObjectPropertyDescriptor(m_functionApply, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().call),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().call, builtinFunctionCall, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().bind),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bind, builtinFunctionBind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().hasInstance)),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.hasInstance]")), builtinFunctionHasInstanceOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Function),
-                      ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinGeneratorFunction.cpp
deleted file mode 100644 (file)
index 329d53f..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "GeneratorObject.h"
-#include "NativeFunctionObject.h"
-#include "runtime/ScriptGeneratorFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinGeneratorFunction(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    size_t argumentVectorCount = argc > 1 ? argc - 1 : 0;
-    Value sourceValue = argc >= 1 ? argv[argc - 1] : Value(String::emptyString);
-    auto functionSource = FunctionObject::createFunctionSourceFromScriptSource(state, state.context()->staticStrings().anonymous, argumentVectorCount, argv, sourceValue, false, true, false, false);
-
-    // Let proto be ? GetPrototypeFromConstructor(newTarget, fallbackProto).
-    if (!newTarget.hasValue()) {
-        newTarget = state.resolveCallee();
-    }
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->generator();
-    });
-
-    return new ScriptGeneratorFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
-}
-
-static Value builtinGeneratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return GeneratorObject::generatorResume(state, thisValue, argc > 0 ? argv[0] : Value());
-}
-
-static Value builtinGeneratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return GeneratorObject::generatorResumeAbrupt(state, thisValue, argc > 0 ? argv[0] : Value(), GeneratorObject::GeneratorAbruptType::Return);
-}
-
-static Value builtinGeneratorThrow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return GeneratorObject::generatorResumeAbrupt(state, thisValue, argc > 0 ? argv[0] : Value(), GeneratorObject::GeneratorAbruptType::Throw);
-}
-
-void GlobalObject::installGenerator(ExecutionState& state)
-{
-    // %GeneratorFunction% : The constructor of generator objects
-    m_generatorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().GeneratorFunction, builtinGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_generatorFunction->setGlobalIntrinsicObject(state);
-
-    // %Generator% : The initial value of the prototype property of %GeneratorFunction%
-    m_generator = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().GeneratorFunction, nullptr, 0, NativeFunctionInfo::Strict));
-    m_generator->setGlobalIntrinsicObject(state, true);
-    m_generatorFunction->setFunctionPrototype(state, m_generator);
-
-
-    // 25.2.3.1 The initial value of GeneratorFunction.prototype.constructor is the intrinsic object %GeneratorFunction%.
-    m_generator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_generatorFunction, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // %GeneratorPrototype% : The initial value of the prototype property of %Generator%
-    m_generatorPrototype = new Object(state, m_iteratorPrototype);
-    m_generatorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_generator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().prototype), ObjectPropertyDescriptor(m_generatorPrototype, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    // 25.2.3.3 GeneratorFunction.prototype [ @@toStringTag ]
-    // The initial value of the @@toStringTag property is the String value "GeneratorFunction"..
-    // This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
-    m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                  ObjectPropertyDescriptor(Value(state.context()->staticStrings().GeneratorFunction.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // The initial value of Generator.prototype.constructor is the intrinsic object %Generator%.
-    m_generatorPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_generator, ObjectPropertyDescriptor::ConfigurablePresent));
-
-    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinGeneratorNext, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringReturn),
-                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringReturn, builtinGeneratorReturn, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringThrow),
-                                                           ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringThrow, builtinGeneratorThrow, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // http://www.ecma-international.org/ecma-262/6.0/#sec-generatorfunction.prototype-@@tostringtag
-    m_generatorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                           ObjectPropertyDescriptor(Value(state.context()->staticStrings().Generator.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIntl.cpp
deleted file mode 100644 (file)
index c7604a1..0000000
+++ /dev/null
@@ -1,1148 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2017-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "StringObject.h"
-#include "ArrayObject.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "DateObject.h"
-#include "BigInt.h"
-#include "Intl.h"
-#include "IntlCollator.h"
-#include "IntlNumberFormat.h"
-#include "IntlDateTimeFormat.h"
-#include "IntlPluralRules.h"
-#include "IntlLocale.h"
-#include "IntlRelativeTimeFormat.h"
-
-namespace Escargot {
-
-static Value builtinIntlCollatorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl.collator
-    Value locales, options;
-    if (argc >= 1) {
-        locales = argv[0];
-    }
-    if (argc >= 2) {
-        options = argv[1];
-    }
-
-    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
-    if (!newTarget) {
-        newTarget = state.resolveCallee();
-    }
-
-    // Let internalSlotsList be « [[InitializedCollator]], [[Locale]], [[Usage]], [[Sensitivity]], [[IgnorePunctuation]], [[Collation]], [[BoundCompare]] ».
-    // If %Collator%.[[RelevantExtensionKeys]] contains "kn", then
-    // Append [[Numeric]] as the last element of internalSlotsList.
-    // If %Collator%.[[RelevantExtensionKeys]] contains "kf", then
-    // Append [[CaseFirst]] as the last element of internalSlotsList.
-    // Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%CollatorPrototype%", internalSlotsList).
-    // Return ? InitializeCollator(collator, locales, options).
-    return IntlCollator::create(state, newTarget->getFunctionRealm(state), locales, options);
-}
-
-static Value builtinIntlCollatorCompare(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    FunctionObject* callee = state.resolveCallee();
-    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* colllator = callee->asObject();
-
-    String* x = argv[0].toString(state);
-    String* y = argv[1].toString(state);
-
-    return Value(IntlCollator::compare(state, colllator, x, y));
-}
-
-static Value builtinIntlCollatorCompareGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-    FunctionObject* fn;
-    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyCompareFunction()));
-    if (g.hasValue()) {
-        fn = g.value(state, internalSlot).asFunction();
-    } else {
-        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlCollatorCompare, 2, NativeFunctionInfo::Strict));
-        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCompareFunction()), Value(fn), internalSlot);
-        fn->setInternalSlot(internalSlot);
-    }
-
-    return fn;
-}
-
-static Value builtinIntlCollatorResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-    auto r = IntlCollator::resolvedOptions(state, internalSlot);
-    Object* result = new Object(state);
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(r.locale, ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage()), ObjectPropertyDescriptor(r.usage, ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), ObjectPropertyDescriptor(r.sensitivity, ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation()), ObjectPropertyDescriptor(Value(r.ignorePunctuation), ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().collation), ObjectPropertyDescriptor(r.collation, ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().numeric), ObjectPropertyDescriptor(Value(r.numeric), ObjectPropertyDescriptor::AllPresent));
-    result->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().caseFirst), ObjectPropertyDescriptor(Value(r.caseFirst), ObjectPropertyDescriptor::AllPresent));
-    return result;
-}
-
-static Value builtinIntlCollatorSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If options is not provided, then let options be undefined.
-    Value locales = argv[0];
-    Value options;
-    if (argc >= 2) {
-        options = argv[1];
-    }
-    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.Collator.
-    const auto& availableLocales = state.context()->vmInstance()->intlCollatorAvailableLocales();
-    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
-    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
-}
-
-
-static Value builtinIntlDateTimeFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value locales, options;
-    if (argc >= 1) {
-        locales = argv[0];
-    }
-    if (argc >= 2) {
-        options = argv[1];
-    }
-
-    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
-    Object* newTargetVariable;
-    if (!newTarget.hasValue()) {
-        newTargetVariable = state.resolveCallee();
-    } else {
-        newTargetVariable = newTarget.value();
-    }
-
-    // Let dateTimeFormat be ? OrdinaryCreateFromConstructor(newTarget, "%DateTimeFormatPrototype%", « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[Hour]], [[Minute]], [[Second]], [[TimeZoneName]], [[HourCycle]], [[Pattern]], [[BoundFormat]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTargetVariable, [](ExecutionState& state, Context* realm) -> Object* {
-        return realm->globalObject()->intlDateTimeFormatPrototype();
-    });
-    Object* dateTimeFormat = new Object(state, proto);
-    IntlDateTimeFormat::initialize(state, dateTimeFormat, locales, options);
-    return dateTimeFormat;
-}
-
-static Value builtinIntlDateTimeFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    FunctionObject* callee = state.resolveCallee();
-    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* dateTimeFormat = callee->asObject();
-    double value;
-    if (argc == 0 || argv[0].isUndefined()) {
-        value = DateObject::currentTime();
-    } else {
-        value = argv[0].toNumber(state);
-    }
-    auto result = IntlDateTimeFormat::format(state, dateTimeFormat, value);
-
-    return Value(new UTF16String(result.data(), result.length()));
-}
-
-static Value builtinIntlDateTimeFormatFormatGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-    FunctionObject* fn;
-    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().format));
-    if (g.hasValue()) {
-        fn = g.value(state, internalSlot).asFunction();
-    } else {
-        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlDateTimeFormatFormat, 1, NativeFunctionInfo::Strict));
-        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().format), Value(fn), internalSlot);
-        fn->setInternalSlot(internalSlot);
-    }
-
-    return fn;
-}
-
-static Value builtinIntlDateTimeFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let dtf be this value.
-    // If Type(dtf) is not Object, throw a TypeError exception.
-    // If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception.
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-    Value date = argv[0];
-    double x;
-    // If date is undefined, then
-    if (date.isUndefined()) {
-        // Let x be Call(%Date_now%, undefined).
-        x = DateObject::currentTime();
-    } else {
-        // Else,
-        // Let x be ? ToNumber(date).
-        x = date.toNumber(state);
-    }
-    // Return ? FormatDateTimeToParts(dtf, x).
-    return IntlDateTimeFormat::formatToParts(state, thisValue.asObject(), x);
-}
-
-static void setFormatOpt(ExecutionState& state, Object* internalSlot, Object* result, const char* pName)
-{
-    String* prop = String::fromASCII(pName);
-
-    ObjectGetResult r;
-    r = internalSlot->get(state, ObjectPropertyName(state, prop));
-
-    if (r.hasValue()) {
-        result->defineOwnProperty(state, ObjectPropertyName(state, prop), ObjectPropertyDescriptor(Value(r.value(state, internalSlot)), ObjectPropertyDescriptor::AllPresent));
-    }
-}
-
-static Value builtinIntlDateTimeFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-
-    Object* result = new Object(state);
-
-    setFormatOpt(state, internalSlot, result, "locale");
-    setFormatOpt(state, internalSlot, result, "calendar");
-    setFormatOpt(state, internalSlot, result, "numberingSystem");
-    setFormatOpt(state, internalSlot, result, "timeZone");
-    setFormatOpt(state, internalSlot, result, "hourCycle");
-    setFormatOpt(state, internalSlot, result, "hour12");
-    setFormatOpt(state, internalSlot, result, "weekday");
-    setFormatOpt(state, internalSlot, result, "era");
-    setFormatOpt(state, internalSlot, result, "year");
-    setFormatOpt(state, internalSlot, result, "month");
-    setFormatOpt(state, internalSlot, result, "day");
-    setFormatOpt(state, internalSlot, result, "hour");
-    setFormatOpt(state, internalSlot, result, "minute");
-    setFormatOpt(state, internalSlot, result, "second");
-    setFormatOpt(state, internalSlot, result, "timeZoneName");
-
-    return Value(result);
-}
-
-static Value builtinIntlDateTimeFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If options is not provided, then let options be undefined.
-    Value locales = argv[0];
-    Value options;
-    if (argc >= 2) {
-        options = argv[1];
-    }
-    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.DateTimeFormat.
-    const auto& availableLocales = state.context()->vmInstance()->intlDateTimeFormatAvailableLocales();
-    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
-    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
-}
-
-static Value builtinIntlNumberFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    FunctionObject* callee = state.resolveCallee();
-    if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* numberFormat = callee->asObject();
-
-    UTF16StringDataNonGCStd result;
-    auto numeric = argv[0].toNumeric(state);
-    if (numeric.second) {
-        result = IntlNumberFormat::format(state, numberFormat, numeric.first.asBigInt()->toString());
-    } else {
-        result = IntlNumberFormat::format(state, numberFormat, numeric.first.asNumber());
-    }
-
-    return new UTF16String(result.data(), result.length());
-}
-
-static Value builtinIntlNumberFormatFormatGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-    FunctionObject* fn;
-    auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().format));
-    if (g.hasValue()) {
-        fn = g.value(state, internalSlot).asFunction();
-    } else {
-        fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlNumberFormatFormat, 1, NativeFunctionInfo::Strict));
-        internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().format), Value(fn), internalSlot);
-        fn->setInternalSlot(internalSlot);
-    }
-
-    return fn;
-}
-
-static Value builtinIntlNumberFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value locales, options;
-    if (argc >= 1) {
-        locales = argv[0];
-    }
-    if (argc >= 2) {
-        options = argv[1];
-    }
-
-    // If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
-    Object* newTargetVariable;
-    if (!newTarget.hasValue()) {
-        newTargetVariable = state.resolveCallee();
-    } else {
-        newTargetVariable = newTarget.value();
-    }
-
-    // Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget, "%NumberFormatPrototype%", « [[InitializedNumberFormat]], [[Locale]], [[DataLocale]], [[NumberingSystem]], [[Style]], [[Unit]], [[UnitDisplay]], [[Currency]], [[CurrencyDisplay]], [[CurrencySign]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]], [[Notation]], [[CompactDisplay]], [[UseGrouping]], [[SignDisplay]], [[BoundFormat]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTargetVariable, [](ExecutionState& state, Context* realm) -> Object* {
-        return realm->globalObject()->intlNumberFormatPrototype();
-    });
-    Object* numberFormat = new Object(state, proto);
-    IntlNumberFormat::initialize(state, numberFormat, locales, options);
-    return numberFormat;
-}
-
-static Value builtinIntlNumberFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, state.context()->staticStrings().lazyInitializedNumberFormat())) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    Object* internalSlot = thisValue.asObject()->internalSlot();
-    Object* result = new Object(state);
-
-    setFormatOpt(state, internalSlot, result, "locale");
-    setFormatOpt(state, internalSlot, result, "numberingSystem");
-    setFormatOpt(state, internalSlot, result, "style");
-    setFormatOpt(state, internalSlot, result, "currency");
-    setFormatOpt(state, internalSlot, result, "currencyDisplay");
-    setFormatOpt(state, internalSlot, result, "currencySign");
-    setFormatOpt(state, internalSlot, result, "unit");
-    setFormatOpt(state, internalSlot, result, "unitDisplay");
-    setFormatOpt(state, internalSlot, result, "minimumIntegerDigits");
-    setFormatOpt(state, internalSlot, result, "minimumFractionDigits");
-    setFormatOpt(state, internalSlot, result, "maximumFractionDigits");
-    setFormatOpt(state, internalSlot, result, "minimumSignificantDigits");
-    setFormatOpt(state, internalSlot, result, "maximumSignificantDigits");
-    setFormatOpt(state, internalSlot, result, "useGrouping");
-    setFormatOpt(state, internalSlot, result, "notation");
-    setFormatOpt(state, internalSlot, result, "compactDisplay");
-    setFormatOpt(state, internalSlot, result, "signDisplay");
-    return result;
-}
-
-static Value builtinIntlNumberFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let nf be the this value.
-    // If Type(nf) is not Object, throw a TypeError exception.
-    // If nf does not have an [[InitializedNumberFormat]] internal slot, throw a TypeError exception.
-    if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, state.context()->staticStrings().lazyInitializedNumberFormat())) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-    // Let x be ? ToNumeric(value).
-    double x = argv[0].toNumber(state);
-    // Return ? FormatNumericToParts(nf, x).
-    return IntlNumberFormat::formatToParts(state, thisValue.asObject(), x);
-}
-
-static Value builtinIntlNumberFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If options is not provided, then let options be undefined.
-    Value locales = argv[0];
-    Value options;
-    if (argc >= 2) {
-        options = argv[1];
-    }
-    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.NumberFormat.
-    const auto& availableLocales = state.context()->vmInstance()->intlNumberFormatAvailableLocales();
-    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
-    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
-}
-
-static Value builtinIntlPluralRulesConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, throw a TypeError exception.
-    if (!newTarget) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-#if defined(ENABLE_RUNTIME_ICU_BINDER)
-    UVersionInfo versionArray;
-    u_getVersion(versionArray);
-    if (versionArray[0] < 60) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.PluralRules needs 60+ version of ICU");
-    }
-#endif
-
-    Value locales = argc >= 1 ? argv[0] : Value();
-    Value options = argc >= 2 ? argv[1] : Value();
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->intlPluralRulesPrototype();
-    });
-
-    return new IntlPluralRulesObject(state, proto, locales, options);
-}
-
-static Value builtinIntlPluralRulesSelect(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl.pluralrules.prototype.select
-    // Let pr be the this value.
-    // If Type(pr) is not Object, throw a TypeError exception.
-    // If pr does not have an [[InitializedPluralRules]] internal slot, throw a TypeError exception.
-    if (!thisValue.isObject() || !thisValue.asObject()->isIntlPluralRulesObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-    // Let n be ? ToNumber(value).
-    double n = argv[0].toNumber(state);
-    // Return ? ResolvePlural(pr, n).
-    return thisValue.asObject()->asIntlPluralRulesObject()->asIntlPluralRulesObject()->resolvePlural(n);
-}
-
-static Value builtinIntlPluralRulesResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let pr be the this value.
-    // If Type(pr) is not Object, throw a TypeError exception.
-    // If pr does not have an [[InitializedPluralRules]] internal slot, throw a TypeError exception.
-    if (!thisValue.isObject() || !thisValue.asObject()->isIntlPluralRulesObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    IntlPluralRulesObject* pr = thisValue.asObject()->asIntlPluralRulesObject();
-
-    // Let options be ! ObjectCreate(%ObjectPrototype%).
-    Object* options = new Object(state);
-    // For each row of Table 8, except the header row, in table order, do
-    // Let p be the Property value of the current row.
-    // Let v be the value of pr's internal slot whose name is the Internal Slot value of the current row.
-    // If v is not undefined, then
-    // Perform ! CreateDataPropertyOrThrow(options, p, v).
-
-
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(pr->locale(), ObjectPropertyDescriptor::AllPresent));
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyType()), ObjectPropertyDescriptor(pr->type(), ObjectPropertyDescriptor::AllPresent));
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits()), ObjectPropertyDescriptor(Value(pr->minimumIntegerDigits()), ObjectPropertyDescriptor::AllPresent));
-
-    if (pr->minimumSignificantDigits()) {
-        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()), ObjectPropertyDescriptor(Value(pr->minimumSignificantDigits().value()), ObjectPropertyDescriptor::AllPresent));
-        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()), ObjectPropertyDescriptor(Value(pr->maximumSignificantDigits().value()), ObjectPropertyDescriptor::AllPresent));
-    } else {
-        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), ObjectPropertyDescriptor(Value(pr->minimumFractionDigits()), ObjectPropertyDescriptor::AllPresent));
-        options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), ObjectPropertyDescriptor(Value(pr->maximumFractionDigits()), ObjectPropertyDescriptor::AllPresent));
-    }
-
-
-    // Let pluralCategories be a List of Strings representing the possible results of PluralRuleSelect for the selected locale pr.[[Locale]]. This List consists of unique string values, from the the list "zero", "one", "two", "few", "many" and "other", that are relevant for the locale whose localization is specified in LDML Language Plural Rules.
-    // Perform ! CreateDataProperty(options, "pluralCategories", CreateArrayFromList(pluralCategories)).
-    ArrayObject* pluralCategories = new ArrayObject(state);
-
-    UErrorCode status = U_ZERO_ERROR;
-    UEnumeration* ue = uplrules_getKeywords(pr->icuPluralRules(), &status);
-    ASSERT(U_SUCCESS(status));
-    uint32_t i = 0;
-
-    do {
-        int32_t size;
-        const char* str = uenum_next(ue, &size, &status);
-        ASSERT(U_SUCCESS(status));
-
-        if (!str) {
-            break;
-        }
-
-        String* s = String::fromUTF8(str, size);
-        pluralCategories->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, (size_t)i), ObjectPropertyDescriptor(Value(s), ObjectPropertyDescriptor::AllPresent));
-        i++;
-    } while (true);
-
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(AtomicString(state.context()->atomicStringMap(), "pluralCategories", sizeof("pluralCategories") - 1, AtomicString::FromExternalMemory)),
-                                              ObjectPropertyDescriptor(pluralCategories, ObjectPropertyDescriptor::AllPresent));
-
-    uenum_close(ue);
-    // Return options.
-    return options;
-}
-
-static Value builtinIntlPluralRulesSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If options is not provided, then let options be undefined.
-    Value locales = argv[0];
-    Value options;
-    if (argc >= 2) {
-        options = argv[1];
-    }
-    // Let availableLocales be the value of the [[availableLocales]] internal property of the standard built-in object that is the initial value of Intl.Collator.
-    const auto& availableLocales = state.context()->vmInstance()->intlPluralRulesAvailableLocales();
-    // Let requestedLocales be the result of calling the CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // Return the result of calling the SupportedLocales abstract operation (defined in 9.2.8) with arguments availableLocales, requestedLocales, and options.
-    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
-}
-
-static Value builtinIntlLocaleConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, throw a TypeError exception.
-    if (!newTarget) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    Value tagValue = argv[0];
-
-    // If Type(tag) is not String or Object, throw a TypeError exception.
-    if (!tagValue.isObject() && !tagValue.isString()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "First argument of Intl.Locale should be String or Object");
-    }
-
-    String* tag;
-    // If Type(tag) is Object and tag has an [[InitializedLocale]] internal slot, then
-    if (tagValue.isObject() && tagValue.asObject()->isIntlLocaleObject()) {
-        // Let tag be tag.[[Locale]].
-        tag = tagValue.asObject()->asIntlLocaleObject()->locale();
-    } else {
-        // Else,
-        // Let tag be ? ToString(tag).
-        tag = tagValue.toString(state);
-    }
-
-    Optional<Object*> options;
-    // If options is undefined, then
-    if (argc <= 1 || argv[1].isUndefined()) {
-        // Let options be ! ObjectCreate(null).
-    } else {
-        // Let options be ? ToObject(options).
-        options = argv[1].toObject(state);
-    }
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->intlLocalePrototype();
-    });
-    return new IntlLocaleObject(state, proto, tag, options);
-}
-
-static Value builtinIntlLocaleToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let loc be the this value.
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-    // Return loc.[[Locale]].
-    return loc.asObject()->asIntlLocaleObject()->locale();
-}
-
-static Value builtinIntlLocaleBaseNameGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->baseName();
-}
-
-static Value builtinIntlLocaleCalendarGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->calendar().hasValue() ? loc.asObject()->asIntlLocaleObject()->calendar().value() : Value();
-}
-
-static Value builtinIntlLocaleCaseFirstGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->caseFirst().hasValue() ? loc.asObject()->asIntlLocaleObject()->caseFirst().value() : Value();
-}
-
-static Value builtinIntlLocaleCollationGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->collation().hasValue() ? loc.asObject()->asIntlLocaleObject()->collation().value() : Value();
-}
-
-static Value builtinIntlLocaleHourCycleGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->hourCycle().hasValue() ? loc.asObject()->asIntlLocaleObject()->hourCycle().value() : Value();
-}
-
-static Value builtinIntlLocaleNumericGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->numeric().hasValue() ? Value(loc.asObject()->asIntlLocaleObject()->numeric().value()->equals("true")) : Value(false);
-}
-
-static Value builtinIntlLocaleNumberingSystemGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->numberingSystem().hasValue() ? loc.asObject()->asIntlLocaleObject()->numberingSystem().value() : Value();
-}
-
-static Value builtinIntlLocaleLanguageGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->language();
-}
-
-static Value builtinIntlLocaleScriptGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->script();
-}
-
-static Value builtinIntlLocaleRegionGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    return loc.asObject()->asIntlLocaleObject()->region();
-}
-
-static void icuLocleToBCP47Locale(char* buf, size_t len)
-{
-    for (size_t i = 0; i < len; i++) {
-        if (buf[i] == '_') {
-            buf[i] = '-';
-        } else if ((std::numeric_limits<char>::is_signed && buf[i] < 0) || (!std::numeric_limits<char>::is_signed && buf[i] > 127)) {
-            // when using uloc_addLikelySubtags with `und-...` input, old version of ICU shows weird behavior
-            // it contains minus value in string
-            buf[i] = 0;
-            len = i;
-            break;
-        } else if (buf[i] == '@') { // we should ignore tags after '@'. ex) es-Latn-ES@currency=ESP -> es-Latn-ES
-            buf[i] = 0;
-            len = i;
-            break;
-        }
-    }
-
-    for (size_t i = 0; i < len - 1; i++) {
-        if (buf[i] == '-' && buf[i + 1] == '-') {
-            for (size_t j = i; j < len - 1; j++) {
-                buf[j] = buf[j + 1];
-            }
-            len--;
-            buf[len] = 0;
-        }
-    }
-}
-
-static Value builtinIntlLocaleMaximize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    // Let maximal be the result of the Add Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set maximal to loc.[[Locale]].
-    // Return ! Construct(%Locale%, maximal).
-    IntlLocaleObject* localeObject = loc.asObject()->asIntlLocaleObject();
-    String* locale = localeObject->locale();
-    auto u8Locale = locale->toNonGCUTF8StringData();
-    UErrorCode status = U_ZERO_ERROR;
-    char buf[128];
-    int32_t len = uloc_addLikelySubtags(u8Locale.data(), buf, sizeof(buf), &status);
-    if (U_SUCCESS(status)) {
-        icuLocleToBCP47Locale(buf, strlen(buf));
-        StringBuilder sb;
-        sb.appendString(buf);
-        sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
-        return new IntlLocaleObject(state, sb.finalize(), nullptr);
-
-    } else if (status != U_BUFFER_OVERFLOW_ERROR) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Unexpected error is occured while parsing locale");
-    }
-    status = U_ZERO_ERROR;
-    char* newBuf = (char*)alloca(len + 1);
-    uloc_addLikelySubtags(u8Locale.data(), newBuf, len + 1, &status);
-    ASSERT(U_SUCCESS(status));
-
-    icuLocleToBCP47Locale(newBuf, strlen(newBuf));
-    StringBuilder sb;
-    sb.appendString(newBuf);
-    sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
-    return new IntlLocaleObject(state, sb.finalize(), nullptr);
-}
-
-static Value builtinIntlLocaleMinimize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value loc = thisValue;
-    // If Type(loc) is not Object or loc does not have an [[InitializedLocale]] internal slot, then
-    if (!loc.isObject() || !loc.asObject()->isIntlLocaleObject()) {
-        // Throw a TypeError exception.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    // Let minimal be the result of the Remove Likely Subtags algorithm applied to loc.[[Locale]]. If an error is signaled, set minimal to loc.[[Locale]].
-    // Return ! Construct(%Locale%, minimal).
-    IntlLocaleObject* localeObject = loc.asObject()->asIntlLocaleObject();
-    String* locale = localeObject->locale();
-    auto u8Locale = locale->toNonGCUTF8StringData();
-    UErrorCode status = U_ZERO_ERROR;
-    char buf[128];
-    int32_t len = uloc_minimizeSubtags(u8Locale.data(), buf, sizeof(buf), &status);
-    if (U_SUCCESS(status)) {
-        icuLocleToBCP47Locale(buf, len);
-        StringBuilder sb;
-        sb.appendString(buf);
-        sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
-        return new IntlLocaleObject(state, sb.finalize(), nullptr);
-    } else if (status != U_BUFFER_OVERFLOW_ERROR) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Unexpected error is occured while parsing locale");
-    }
-    status = U_ZERO_ERROR;
-    char* newBuf = (char*)alloca(len + 1);
-    len = uloc_minimizeSubtags(u8Locale.data(), newBuf, len + 1, &status);
-    ASSERT(U_SUCCESS(status));
-
-    icuLocleToBCP47Locale(newBuf, len);
-    StringBuilder sb;
-    sb.appendString(newBuf);
-    sb.appendSubString(locale, localeObject->baseName()->length(), locale->length());
-    return new IntlLocaleObject(state, sb.finalize(), nullptr);
-}
-
-static Value builtinIntlRelativeTimeFormatConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, throw a TypeError exception.
-    if (!newTarget) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-#if defined(ENABLE_RUNTIME_ICU_BINDER)
-    UVersionInfo versionArray;
-    u_getVersion(versionArray);
-    if (versionArray[0] < 64) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.RelativeTimeFormat needs 64+ version of ICU");
-    }
-#endif
-
-    Value locales = argc >= 1 ? argv[0] : Value();
-    Value options = argc >= 2 ? argv[1] : Value();
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->intlRelativeTimeFormatPrototype();
-    });
-
-    return new IntlRelativeTimeFormatObject(state, proto, locales, options);
-}
-
-static Value builtinIntlRelativeTimeFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    IntlRelativeTimeFormatObject* r = thisValue.asObject()->asIntlRelativeTimeFormatObject();
-
-    // Let options be ! ObjectCreate(%ObjectPrototype%).
-    Object* options = new Object(state);
-
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), ObjectPropertyDescriptor(r->locale(), ObjectPropertyDescriptor::AllPresent));
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyStyle()), ObjectPropertyDescriptor(r->style(), ObjectPropertyDescriptor::AllPresent));
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().numeric), ObjectPropertyDescriptor(r->numeric(), ObjectPropertyDescriptor::AllPresent));
-    options->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), ObjectPropertyDescriptor(r->numberingSystem(), ObjectPropertyDescriptor::AllPresent));
-
-    return options;
-}
-
-static Value builtinIntlRelativeTimeFormatSupportedLocalesOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value locales = argv[0];
-    Value options;
-    if (argc >= 2) {
-        options = argv[1];
-    }
-    // Let availableLocales be %RelativeTimeFormat%.[[AvailableLocales]].
-    const auto& availableLocales = state.context()->vmInstance()->intlRelativeTimeFormatAvailableLocales();
-    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // Return ? SupportedLocales(availableLocales, requestedLocales, options).
-    return Intl::supportedLocales(state, availableLocales, requestedLocales, options);
-}
-
-static Value builtinIntlRelativeTimeFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    // Let relativeTimeFormat be the this value.
-    // Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
-    // Let value be ? ToNumber(value).
-    double value = argv[0].toNumber(state);
-    // Let unit be ? ToString(unit).
-    String* unit = argv[1].toString(state);
-    // Return ? FormatRelativeTime(relativeTimeFormat, value, unit).
-    return thisValue.asObject()->asIntlRelativeTimeFormatObject()->format(state, value, unit);
-}
-
-static Value builtinIntlRelativeTimeFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isIntlRelativeTimeFormatObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
-    }
-
-    // Let relativeTimeFormat be the this value.
-    // Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
-    // Let value be ? ToNumber(value).
-    double value = argv[0].toNumber(state);
-    // Let unit be ? ToString(unit).
-    String* unit = argv[1].toString(state);
-    // Return ? FormatRelativeTimeToParts(relativeTimeFormat, value, unit).
-    return thisValue.asObject()->asIntlRelativeTimeFormatObject()->formatToParts(state, value, unit);
-}
-
-static Value builtinIntlGetCanonicalLocales(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let ll be ? CanonicalizeLocaleList(locales).
-    ValueVector ll = Intl::canonicalizeLocaleList(state, argv[0]);
-    // Return CreateArrayFromList(ll);
-    return Object::createArrayFromList(state, ll);
-}
-
-void GlobalObject::installIntl(ExecutionState& state)
-{
-    m_intl = new Object(state);
-    m_intl->setGlobalIntrinsicObject(state);
-
-    const StaticStrings* strings = &state.context()->staticStrings();
-    defineOwnProperty(state, ObjectPropertyName(strings->Intl),
-                      ObjectPropertyDescriptor(m_intl, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlCollator = new NativeFunctionObject(state, NativeFunctionInfo(strings->Collator, builtinIntlCollatorConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlCollator->setGlobalIntrinsicObject(state);
-    m_intlCollator->getFunctionPrototype(state).asObject()->setGlobalIntrinsicObject(state);
-
-    FunctionObject* compareFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getCompare, builtinIntlCollatorCompareGetter, 0, NativeFunctionInfo::Strict));
-    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, state.context()->staticStrings().compare,
-                                                                              ObjectPropertyDescriptor(JSGetterSetter(compareFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
-                                                                              ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlCollatorResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlCollator->getFunctionPrototype(state).asObject()->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                              ObjectPropertyDescriptor(strings->intlDotCollator.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlCollator->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
-                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlCollatorSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlDateTimeFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->DateTimeFormat, builtinIntlDateTimeFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlDateTimeFormat->setGlobalIntrinsicObject(state);
-    m_intlDateTimeFormatPrototype = m_intlDateTimeFormat->getFunctionPrototype(state).asObject();
-    m_intlDateTimeFormatPrototype->setGlobalIntrinsicObject(state, true);
-
-    FunctionObject* formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlDateTimeFormatFormatGetter, 0, NativeFunctionInfo::Strict));
-    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
-                                                     ObjectPropertyDescriptor(JSGetterSetter(formatFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlDateTimeFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlDateTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlDateTimeFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlDateTimeFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
-                                            ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlDateTimeFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlNumberFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->NumberFormat, builtinIntlNumberFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlNumberFormat->setGlobalIntrinsicObject(state);
-    m_intlNumberFormatPrototype = m_intlNumberFormat->getFunctionPrototype(state).asObject();
-    m_intlNumberFormatPrototype->setGlobalIntrinsicObject(state, true);
-
-    formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlNumberFormatFormatGetter, 0, NativeFunctionInfo::Strict));
-    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
-                                                   ObjectPropertyDescriptor(JSGetterSetter(formatFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
-                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlNumberFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
-                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlNumberFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlNumberFormatPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                  ObjectPropertyDescriptor(Value(state.context()->staticStrings().Object.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlNumberFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
-                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlNumberFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlPluralRules = new NativeFunctionObject(state, NativeFunctionInfo(strings->PluralRules, builtinIntlPluralRulesConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlPluralRules->setGlobalIntrinsicObject(state);
-
-    m_intlPluralRulesPrototype = m_intlPluralRules->getFunctionPrototype(state).asObject();
-    m_intlPluralRulesPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_intlPluralRulesPrototype->defineOwnProperty(state, state.context()->staticStrings().select,
-                                                  ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->select, builtinIntlPluralRulesSelect, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlPluralRulesPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
-                                                  ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlPluralRulesResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlPluralRulesPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                 ObjectPropertyDescriptor(Value(state.context()->staticStrings().Object.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlPluralRules->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlPluralRulesSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-
-    m_intlLocale = new NativeFunctionObject(state, NativeFunctionInfo(strings->Locale, builtinIntlLocaleConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlLocale->setGlobalIntrinsicObject(state);
-
-    m_intlLocalePrototype = m_intlLocale->getFunctionPrototype(state).asObject();
-    m_intlLocalePrototype->setGlobalIntrinsicObject(state, true);
-
-    m_intlLocalePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                            ObjectPropertyDescriptor(Value(state.context()->staticStrings().intlDotLocale.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getBaseName, builtinIntlLocaleBaseNameGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().baseName), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCalendar, builtinIntlLocaleCalendarGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().calendar), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCaseFirst, builtinIntlLocaleCaseFirstGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().caseFirst), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getCollation, builtinIntlLocaleCollationGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().collation), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getHourCycle, builtinIntlLocaleHourCycleGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().hourCycle), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getNumeric, builtinIntlLocaleNumericGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().numeric), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getNumberingSystem, builtinIntlLocaleNumberingSystemGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().numberingSystem), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getLanguage, builtinIntlLocaleLanguageGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().language), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getScript, builtinIntlLocaleScriptGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().script), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getRegion, builtinIntlLocaleRegionGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_intlLocalePrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().region), desc);
-    }
-
-    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().toString,
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinIntlLocaleToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().maximize,
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->maximize, builtinIntlLocaleMaximize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlLocalePrototype->defineOwnProperty(state, state.context()->staticStrings().minimize,
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->minimize, builtinIntlLocaleMinimize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlRelativeTimeFormat = new NativeFunctionObject(state, NativeFunctionInfo(strings->RelativeTimeFormat, builtinIntlRelativeTimeFormatConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_intlRelativeTimeFormat->setGlobalIntrinsicObject(state);
-
-    m_intlRelativeTimeFormatPrototype = m_intlRelativeTimeFormat->getFunctionPrototype(state).asObject();
-    m_intlRelativeTimeFormatPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_intlRelativeTimeFormatPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                        ObjectPropertyDescriptor(Value(state.context()->staticStrings().intlDotRelativeTimeFormat.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->format, builtinIntlRelativeTimeFormatFormat, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlRelativeTimeFormatFormatToParts, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlRelativeTimeFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().resolvedOptions,
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolvedOptions, builtinIntlRelativeTimeFormatResolvedOptions, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intlRelativeTimeFormat->defineOwnProperty(state, state.context()->staticStrings().supportedLocalesOf,
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->supportedLocalesOf, builtinIntlRelativeTimeFormatSupportedLocalesOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->Collator),
-                              ObjectPropertyDescriptor(m_intlCollator, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->DateTimeFormat),
-                              ObjectPropertyDescriptor(m_intlDateTimeFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->NumberFormat),
-                              ObjectPropertyDescriptor(m_intlNumberFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->PluralRules),
-                              ObjectPropertyDescriptor(m_intlPluralRules, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->Locale),
-                              ObjectPropertyDescriptor(m_intlLocale, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->RelativeTimeFormat),
-                              ObjectPropertyDescriptor(m_intlRelativeTimeFormat, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    FunctionObject* getCanonicalLocales = new NativeFunctionObject(state, NativeFunctionInfo(strings->getCanonicalLocales, builtinIntlGetCanonicalLocales, 1, NativeFunctionInfo::Strict));
-    m_intl->defineOwnProperty(state, ObjectPropertyName(strings->getCanonicalLocales),
-                              ObjectPropertyDescriptor(getCanonicalLocales, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
-
-#endif // ENABLE_ICU
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinIterator.cpp
deleted file mode 100644 (file)
index 1ea284f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return thisValue;
-}
-
-void GlobalObject::installIterator(ExecutionState& state)
-{
-    m_iteratorPrototype = new Object(state);
-    m_iteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-@@iterator
-    FunctionObject* fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinIteratorIterator, 0, NativeFunctionInfo::Strict));
-    m_iteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                          ObjectPropertyDescriptor(fn,
-                                                                                   (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinJSON.cpp
deleted file mode 100644 (file)
index 7d3bc46..0000000
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "StringObject.h"
-#include "ArrayObject.h"
-#include "TypedArrayObject.h"
-#include "BooleanObject.h"
-#include "BigIntObject.h"
-#include "NativeFunctionObject.h"
-
-#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag
-#define RAPIDJSON_ERROR_CHARTYPE char
-#include <rapidjson/document.h>
-#include <rapidjson/filereadstream.h>
-#include <rapidjson/memorystream.h>
-#include <rapidjson/internal/dtoa.h>
-#include <rapidjson/stringbuffer.h>
-#include <rapidjson/writer.h>
-#include <rapidjson/error/en.h>
-
-namespace Escargot {
-
-template <typename Encoding>
-struct JSONStringStream {
-    typedef typename Encoding::Ch Ch;
-
-    JSONStringStream(const Ch* src, size_t length)
-        : src_(src)
-        , head_(src)
-        , tail_(src + length)
-    {
-    }
-
-    Ch Peek() const
-    {
-        if (UNLIKELY(tail_ <= src_)) {
-            return 0;
-        }
-        return *src_;
-    }
-    Ch Take()
-    {
-        if (UNLIKELY(tail_ <= src_)) {
-            return 0;
-        }
-        return *src_++;
-    }
-    size_t Tell() const { return static_cast<size_t>(src_ - head_); }
-    Ch* PutBegin()
-    {
-        RAPIDJSON_ASSERT(false);
-        return 0;
-    }
-    void Put(Ch) { RAPIDJSON_ASSERT(false); }
-    void Flush() { RAPIDJSON_ASSERT(false); }
-    size_t PutEnd(Ch*)
-    {
-        RAPIDJSON_ASSERT(false);
-        return 0;
-    }
-
-    const Ch* src_; //!< Current read position.
-    const Ch* head_; //!< Original head of the string.
-    const Ch* tail_;
-};
-
-template <typename CharType, typename JSONCharType>
-static Value parseJSONWorker(ExecutionState& state, rapidjson::GenericValue<JSONCharType>& value)
-{
-    volatile int sp;
-    size_t currentStackBase = (size_t)&sp;
-#ifdef STACK_GROWS_DOWN
-    if (UNLIKELY(state.stackLimit() > currentStackBase)) {
-#else
-    if (UNLIKELY(state.stackLimit() < currentStackBase)) {
-#endif
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Maximum call stack size exceeded");
-    }
-
-    if (value.IsBool()) {
-        return Value(value.GetBool());
-    } else if (value.IsInt()) {
-        return Value(value.GetInt());
-    } else if (value.IsUint()) {
-        return Value(value.GetUint());
-    } else if (value.IsInt64()) {
-        return Value(value.GetInt64());
-    } else if (value.IsUint64()) {
-        return Value(value.GetUint64());
-    } else if (value.IsDouble()) {
-        return Value(value.GetDouble());
-    } else if (value.IsNull()) {
-        return Value(Value::Null);
-    } else if (value.IsString()) {
-        if (std::is_same<CharType, char16_t>::value) {
-            const char16_t* chars = (const char16_t*)value.GetString();
-            unsigned len = value.GetStringLength();
-            if (isAllLatin1(chars, len)) {
-                return new Latin1String(chars, len);
-            } else {
-                return new UTF16String(chars, len);
-            }
-        } else {
-            const char* valueAsString = (const char*)value.GetString();
-            if (isAllASCII(valueAsString, strlen(valueAsString))) {
-                return new ASCIIString(valueAsString);
-            } else {
-                return new UTF16String(utf8StringToUTF16String(valueAsString, strlen(valueAsString)));
-            }
-        }
-    } else if (value.IsArray()) {
-        ArrayObject* arr = new ArrayObject(state, value.Size(), false);
-        for (size_t i = 0; i < value.Size(); i++) {
-            arr->defineOwnIndexedPropertyWithExpandedLength(state, i, parseJSONWorker<CharType, JSONCharType>(state, value[i]));
-        }
-        return arr;
-    } else if (value.IsObject()) {
-        Object* obj = new Object(state);
-        if (value.MemberCount() > ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE) {
-            obj->markThisObjectDontNeedStructureTransitionTable();
-        }
-        auto iter = value.MemberBegin();
-        while (iter != value.MemberEnd()) {
-            Value propertyName = parseJSONWorker<CharType, JSONCharType>(state, iter->name);
-            ASSERT(propertyName.isString());
-            obj->defineOwnProperty(state, ObjectPropertyName(AtomicString(state, propertyName.toString(state))),
-                                   ObjectPropertyDescriptor(parseJSONWorker<CharType, JSONCharType>(state, iter->value), ObjectPropertyDescriptor::AllPresent));
-            iter++;
-        }
-        return obj;
-    } else {
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-}
-
-template <typename CharType, typename JSONCharType>
-static Value parseJSON(ExecutionState& state, const CharType* data, size_t length)
-{
-    auto strings = &state.context()->staticStrings();
-    rapidjson::GenericDocument<JSONCharType> jsonDocument;
-
-    JSONStringStream<JSONCharType> stringStream(data, length);
-    jsonDocument.ParseStream(stringStream);
-    if (jsonDocument.HasParseError()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::SyntaxError, strings->JSON.string(), true, strings->parse.string(), rapidjson::GetParseError_En(jsonDocument.GetParseError()));
-    }
-
-    return parseJSONWorker<CharType, JSONCharType>(state, jsonDocument);
-}
-
-String* codePointTo4digitString(int codepoint)
-{
-    StringBuilder ret;
-    int d = 16 * 16 * 16;
-    for (int i = 0; i < 4; ++i) {
-        if (codepoint >= d) {
-            char16_t c;
-            if (codepoint / d < 10) {
-                c = (codepoint / d) + '0';
-            } else {
-                c = (codepoint / d) - 10 + 'a';
-            }
-            codepoint %= d;
-            ret.appendChar(c);
-        } else {
-            ret.appendChar('0');
-        }
-        d >>= 4;
-    }
-
-    return ret.finalize();
-}
-
-static Value builtinJSONParse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-
-    // 1, 2, 3
-    String* JText = argv[0].toString(state);
-    Value unfiltered;
-
-    if (JText->has8BitContent()) {
-        size_t len = JText->length();
-        char16_t* char16Buf = new char16_t[len];
-        std::unique_ptr<char16_t[]> buf(char16Buf);
-        const LChar* srcBuf = JText->characters8();
-        for (size_t i = 0; i < len; i++) {
-            char16Buf[i] = srcBuf[i];
-        }
-        unfiltered = parseJSON<char16_t, rapidjson::UTF16<char16_t>>(state, buf.get(), JText->length());
-    } else {
-        unfiltered = parseJSON<char16_t, rapidjson::UTF16<char16_t>>(state, JText->characters16(), JText->length());
-    }
-
-    // 4
-    Value reviver = argv[1];
-    if (reviver.isCallable()) {
-        Object* root = new Object(state);
-        root->markThisObjectDontNeedStructureTransitionTable();
-        root->defineOwnProperty(state, ObjectPropertyName(state, String::emptyString), ObjectPropertyDescriptor(unfiltered, ObjectPropertyDescriptor::AllPresent));
-        std::function<Value(Value, const ObjectPropertyName&)> Walk;
-        Walk = [&](Value holder, const ObjectPropertyName& name) -> Value {
-            Value val = holder.asPointerValue()->asObject()->get(state, name).value(state, holder);
-            if (val.isObject()) {
-                if (val.asObject()->isArray(state)) {
-                    Object* object = val.asObject();
-                    uint32_t i = 0;
-                    uint32_t len = object->length(state);
-                    while (i < len) {
-                        Value newElement = Walk(val, ObjectPropertyName(state, Value(i).toString(state)));
-                        if (newElement.isUndefined()) {
-                            object->deleteOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)));
-                        } else {
-                            object->defineOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)), ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
-                        }
-                        i++;
-                    }
-                } else if (val.asObject()->isTypedArrayObject()) {
-                    ArrayBufferView* arrObject = val.asObject()->asArrayBufferView();
-                    uint32_t i = 0;
-                    uint32_t len = arrObject->arrayLength();
-                    while (i < len) {
-                        Value newElement = Walk(val, ObjectPropertyName(state, Value(i).toString(state)));
-                        if (newElement.isUndefined()) {
-                            arrObject->deleteOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)));
-                        } else {
-                            arrObject->defineOwnProperty(state, ObjectPropertyName(state, Value(i).toString(state)), ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
-                        }
-                        i++;
-                    }
-                } else {
-                    Object* object = val.asObject();
-
-                    ObjectPropertyNameVector keys;
-                    if (!object->canUseOwnPropertyKeysFastPath()) {
-                        auto keyValues = Object::enumerableOwnProperties(state, object, EnumerableOwnPropertiesType::Key);
-
-                        for (size_t i = 0; i < keyValues.size(); ++i) {
-                            keys.push_back(ObjectPropertyName(state, keyValues[i]));
-                        }
-                    } else {
-                        object->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& P, const ObjectStructurePropertyDescriptor& desc, void* data) -> bool {
-                            if (desc.isEnumerable()) {
-                                ObjectPropertyNameVector* keys = (ObjectPropertyNameVector*)data;
-                                keys->push_back(P);
-                            }
-                            return true;
-                        },
-                                            &keys);
-                    }
-
-                    for (auto key : keys) {
-                        Value newElement = Walk(val, key);
-                        if (newElement.isUndefined()) {
-                            object->deleteOwnProperty(state, key);
-                        } else {
-                            object->defineOwnProperty(state, key, ObjectPropertyDescriptor(newElement, ObjectPropertyDescriptor::AllPresent));
-                        }
-                    }
-                }
-            }
-            Value arguments[] = { name.toPlainValue(state), val };
-            return Object::call(state, reviver, holder, 2, arguments);
-        };
-        return Walk(root, ObjectPropertyName(state, String::emptyString));
-    }
-
-    // 5
-    return unfiltered;
-}
-
-static void builtinJSONArrayReplacerHelper(ExecutionState& state, ValueVectorWithInlineStorage& propertyList, Value property)
-{
-    String* item;
-
-    if (property.isString()) {
-        item = property.asString();
-    } else if (property.isNumber()) {
-        item = property.toString(state);
-    } else if (property.isObject() && (property.asPointerValue()->isStringObject() || property.asPointerValue()->isNumberObject())) {
-        item = property.toString(state);
-    } else {
-        return;
-    }
-
-    for (size_t i = 0; i < propertyList.size(); i++) {
-        if (propertyList[i].abstractEqualsTo(state, item)) {
-            return;
-        }
-    }
-    propertyList.push_back(Value(item));
-}
-
-static bool builtinJSONStringifyStr(ExecutionState& state, Value key, Object* holder,
-                                    StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
-                                    String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
-                                    LargeStringBuilder& product);
-static void builtinJSONStringifyJA(ExecutionState& state, Object* obj,
-                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
-                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
-                                   LargeStringBuilder& product);
-static void builtinJSONStringifyJO(ExecutionState& state, Object* value,
-                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
-                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
-                                   LargeStringBuilder& product);
-static void builtinJSONStringifyQuote(ExecutionState& state, Value value, LargeStringBuilder& product);
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonproperty
-static bool builtinJSONStringifyStr(ExecutionState& state, Value key, Object* holder,
-                                    StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack,
-                                    String* indent, String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
-                                    LargeStringBuilder& product)
-{
-    Value value = holder->get(state, ObjectPropertyName(state, key)).value(state, holder);
-    if (value.isObject() || value.isBigInt()) {
-        Value toJson = Object::getV(state, value, ObjectPropertyName(state, strings->toJSON));
-        if (toJson.isCallable()) {
-            Value arguments[] = { key.toString(state) };
-            value = Object::call(state, toJson, value, 1, arguments);
-        }
-    }
-
-    if (!replacerFunc.isUndefined()) {
-        Value arguments[] = { key.toString(state), value };
-        value = Object::call(state, replacerFunc, holder, 2, arguments);
-    }
-
-    if (value.isObject()) {
-        if (value.asObject()->isNumberObject()) {
-            value = Value(value.toNumber(state));
-        } else if (value.asObject()->isStringObject()) {
-            value = Value(value.toString(state));
-        } else if (value.asObject()->isBooleanObject()) {
-            value = Value(value.asObject()->asBooleanObject()->primitiveValue());
-        } else if (value.asObject()->isBigIntObject()) {
-            value = Value(value.asObject()->asBigIntObject()->primitiveValue());
-        }
-    }
-    if (value.isNull()) {
-        product.appendString(strings->null.string());
-        return true;
-    }
-    if (value.isBoolean()) {
-        product.appendString(value.asBoolean() ? strings->stringTrue.string() : strings->stringFalse.string());
-        return true;
-    }
-    if (value.isString()) {
-        builtinJSONStringifyQuote(state, value.asString(), product);
-        return true;
-    }
-    if (value.isNumber()) {
-        double d = value.toNumber(state);
-        if (std::isfinite(d)) {
-            product.appendString(value.toString(state));
-            return true;
-        }
-        product.appendString(strings->null.string());
-        return true;
-    }
-    if (value.isBigInt()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Could not serialize a BigInt");
-    }
-    if (value.isObject() && !value.isCallable()) {
-        if (value.asObject()->isArray(state)) {
-            builtinJSONStringifyJA(state, value.asObject(), strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
-        } else {
-            builtinJSONStringifyJO(state, value.asObject(), strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
-        }
-        return true;
-    }
-
-    return false;
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonarray
-static void builtinJSONStringifyJA(ExecutionState& state, Object* obj,
-                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack,
-                                   String* indent, String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList,
-                                   LargeStringBuilder& product)
-{
-    // 1
-    for (size_t i = 0; i < stack.size(); i++) {
-        Value& v = stack[i];
-        if (v == Value(obj)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JAError);
-        }
-    }
-    // 2
-    stack.push_back(Value(obj));
-    // 3
-    String* stepback = indent;
-    // 4
-    StringBuilder newIndent;
-    newIndent.appendString(indent);
-    newIndent.appendString(gap);
-    indent = newIndent.finalize(&state);
-
-    // 6, 7
-    uint32_t len = obj->length(state);
-
-    // Each array element requires at least 1 character for the value, and 1 character for the separator
-    if (len / 2 > STRING_MAXIMUM_LENGTH) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JAError);
-    }
-
-    // 8 ~ 9
-    uint32_t index = 0;
-    bool first = true;
-    String* seperator = strings->asciiTable[(size_t)','].string();
-
-    product.appendChar('[');
-    while (index < len) {
-        if (first) {
-            if (gap->length()) {
-                product.appendChar('\n');
-                product.appendString(indent);
-                StringBuilder seperatorBuilder;
-                seperatorBuilder.appendChar(',');
-                seperatorBuilder.appendChar('\n');
-                seperatorBuilder.appendString(indent);
-                seperator = seperatorBuilder.finalize(&state);
-            }
-            first = false;
-        } else {
-            product.appendString(seperator);
-        }
-
-        bool strP = builtinJSONStringifyStr(state, Value(index), obj, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
-        if (!strP) {
-            product.appendString(strings->null.string());
-        }
-        index++;
-    }
-
-    if (!first && gap->length()) {
-        product.appendChar('\n');
-        product.appendString(stepback);
-    }
-
-    product.appendChar(']');
-
-    // 11
-    stack.pop_back();
-    // 12
-    indent = stepback;
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-serializejsonobject
-static void builtinJSONStringifyJO(ExecutionState& state, Object* value,
-                                   StaticStrings* strings, Value replacerFunc, ValueVectorWithInlineStorage& stack, String* indent,
-                                   String* gap, bool propertyListTouched, ValueVectorWithInlineStorage& propertyList, LargeStringBuilder& product)
-{
-    // 1
-    for (size_t i = 0; i < stack.size(); i++) {
-        if (stack[i] == value) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->JSON.string(), false, strings->stringify.string(), ErrorObject::Messages::GlobalObject_JOError);
-        }
-    }
-    // 2
-    stack.push_back(Value(value));
-    // 3
-    String* stepback = indent;
-    // 4
-    StringBuilder newIndent;
-    newIndent.appendString(indent);
-    newIndent.appendString(gap);
-    indent = newIndent.finalize(&state);
-    // 5, 6
-    ValueVectorWithInlineStorage k;
-    if (propertyListTouched) {
-        k = propertyList;
-    } else {
-        k = Object::enumerableOwnProperties(state, value, EnumerableOwnPropertiesType::Key);
-    }
-
-    // 7 ~ 9
-    bool first = true;
-    size_t len = k.size();
-    String* seperator = strings->asciiTable[(size_t)','].string();
-
-    product.appendChar('{');
-    LargeStringBuilder subProduct;
-    for (size_t i = 0; i < len; i++) {
-        auto strP = builtinJSONStringifyStr(state, k[i], value, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, subProduct);
-        if (strP) {
-            if (first) {
-                if (gap->length()) {
-                    product.appendChar('\n');
-                    product.appendString(indent);
-                    StringBuilder seperatorBuilder;
-                    seperatorBuilder.appendChar(',');
-                    seperatorBuilder.appendChar('\n');
-                    seperatorBuilder.appendString(indent);
-                    seperator = seperatorBuilder.finalize(&state);
-                }
-                first = false;
-            } else {
-                product.appendString(seperator);
-            }
-
-            builtinJSONStringifyQuote(state, k[i], product);
-            product.appendChar(':');
-            if (gap->length() != 0) {
-                product.appendChar(' ');
-            }
-            product.appendStringBuilder(subProduct);
-            subProduct.clear();
-        }
-    }
-
-    if (!first && gap->length()) {
-        product.appendChar('\n');
-        product.appendString(stepback);
-    }
-
-    product.appendChar('}');
-
-    // 11
-    stack.pop_back();
-    // 12
-    indent = stepback;
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-quotejsonstring
-static void builtinJSONStringifyQuote(ExecutionState& state, String* value, LargeStringBuilder& product)
-{
-    auto bad = value->bufferAccessData();
-    product.appendChar('"');
-    for (size_t i = 0; i < bad.length; ++i) {
-        char16_t c = bad.charAt(i);
-
-        switch (c) {
-        case u'\"':
-        case u'\\':
-            product.appendChar('\\');
-            product.appendChar(c);
-            break;
-        case u'\b':
-            product.appendChar('\\');
-            product.appendChar('b');
-            break;
-        case u'\f':
-            product.appendChar('\\');
-            product.appendChar('f');
-            break;
-        case u'\n':
-            product.appendChar('\\');
-            product.appendChar('n');
-            break;
-        case u'\r':
-            product.appendChar('\\');
-            product.appendChar('r');
-            break;
-        case u'\t':
-            product.appendChar('\\');
-            product.appendChar('t');
-            break;
-        case 0:
-        case 1:
-        case 2:
-        case 3:
-        case 4:
-        case 5:
-        case 6:
-        case 7:
-        case 11:
-        case 14:
-        case 15:
-        case 16:
-        case 17:
-        case 18:
-        case 19:
-        case 20:
-        case 21:
-        case 22:
-        case 23:
-        case 24:
-        case 25:
-        case 26:
-        case 27:
-        case 28:
-        case 29:
-        case 30:
-        case 31:
-            product.appendChar('\\');
-            product.appendChar('u');
-            product.appendString(codePointTo4digitString(c));
-            break;
-        default:
-            product.appendChar(c);
-        }
-    }
-    product.appendChar('"');
-}
-
-static void builtinJSONStringifyQuote(ExecutionState& state, Value value, LargeStringBuilder& product)
-{
-    String* str = value.toString(state);
-    builtinJSONStringifyQuote(state, str, product);
-}
-
-static Value builtinJSONStringify(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-
-    // 1, 2, 3
-    Value value = argv[0];
-    Value replacer = argv[1];
-    Value space = argv[2];
-    String* indent = String::emptyString;
-    ValueVectorWithInlineStorage stack;
-    ValueVectorWithInlineStorage propertyList;
-    bool propertyListTouched = false;
-
-    // 4
-    Value replacerFunc;
-    if (replacer.isObject()) {
-        if (replacer.isCallable()) {
-            replacerFunc = replacer;
-        } else if (replacer.asObject()->isArrayObject()) {
-            propertyListTouched = true;
-            ArrayObject* arrObject = replacer.asObject()->asArrayObject();
-
-            std::vector<Value::ValueIndex> indexes;
-            arrObject->enumeration(state, [](ExecutionState& state, Object* self, const ObjectPropertyName& P, const ObjectStructurePropertyDescriptor& desc, void* data) -> bool {
-                Value::ValueIndex idx = P.toPlainValue(state).toNumber(state);
-                if (idx != Value::InvalidIndexValue) {
-                    std::vector<Value::ValueIndex>* indexes = (std::vector<Value::ValueIndex>*)data;
-                    indexes->push_back(idx);
-                }
-                return true;
-            },
-                                   &indexes);
-            std::sort(indexes.begin(), indexes.end(), std::less<Value::ValueIndex>());
-            for (uint32_t i = 0; i < indexes.size(); ++i) {
-                Value property = arrObject->get(state, ObjectPropertyName(state, Value(indexes[i]))).value(state, arrObject);
-                builtinJSONArrayReplacerHelper(state, propertyList, property);
-            }
-        } else if (replacer.asObject()->isArray(state)) {
-            propertyListTouched = true;
-            Object* replacerObj = replacer.asObject();
-            uint64_t len = replacerObj->length(state);
-            uint64_t k = 0;
-
-            while (k < len) {
-                Value v = replacerObj->getIndexedProperty(state, Value(k)).value(state, replacerObj);
-                builtinJSONArrayReplacerHelper(state, propertyList, v);
-                k++;
-            }
-        }
-    }
-
-    // 5
-    if (space.isObject()) {
-        if (space.isPointerValue() && space.asPointerValue()->isNumberObject()) {
-            space = Value(space.toNumber(state));
-        } else if (space.isPointerValue() && space.asPointerValue()->isStringObject()) {
-            space = space.toString(state);
-        }
-    }
-
-    // 6, 7, 8
-    String* gap = String::emptyString;
-    if (space.isNumber()) {
-        int space_cnt = std::min(space.toInteger(state), 10.0);
-        if (space_cnt >= 1) {
-            UTF8StringData gapData;
-            gapData.resizeWithUninitializedValues(space_cnt);
-            for (int i = 0; i < space_cnt; i++) {
-                gapData[i] = ' ';
-            }
-            gap = new ASCIIString(gapData.data(), gapData.length());
-        }
-    } else if (space.isString()) {
-        if (space.asString()->length() <= 10) {
-            gap = space.asString();
-        } else {
-            gap = space.asString()->substring(0, 10);
-        }
-    }
-
-    // 9
-    Object* wrapper = new Object(state);
-    // 10
-    wrapper->defineOwnProperty(state, ObjectPropertyName(state, String::emptyString), ObjectPropertyDescriptor(value, ObjectPropertyDescriptor::AllPresent));
-    LargeStringBuilder product;
-    auto ret = builtinJSONStringifyStr(state, String::emptyString, wrapper, strings, replacerFunc, stack, indent, gap, propertyListTouched, propertyList, product);
-    if (ret) {
-        return product.finalize(&state);
-    }
-    return Value();
-}
-
-void GlobalObject::installJSON(ExecutionState& state)
-{
-    m_json = new Object(state);
-    m_json->setGlobalIntrinsicObject(state);
-    m_json->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                             ObjectPropertyDescriptor(Value(state.context()->staticStrings().JSON.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().JSON),
-                      ObjectPropertyDescriptor(m_json, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_jsonParse = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().parse, builtinJSONParse, 2, NativeFunctionInfo::Strict));
-    m_json->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parse),
-                              ObjectPropertyDescriptor(m_jsonParse,
-                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_jsonStringify = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringify, builtinJSONStringify, 3, NativeFunctionInfo::Strict));
-    m_json->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringify),
-                              ObjectPropertyDescriptor(m_jsonStringify,
-                                                       (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMap.cpp
deleted file mode 100644 (file)
index 329311b..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "MapObject.h"
-#include "IteratorObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinMapConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    // Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
-    // Set map's [[MapData]] internal slot to a new empty List.
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->mapPrototype();
-    });
-    MapObject* map = new MapObject(state, proto);
-
-    // If iterable is not present, or is either undefined or null, return map.
-    if (argc == 0 || argv[0].isUndefinedOrNull()) {
-        return map;
-    }
-
-    Value iterable = argv[0];
-
-    // Let adder be ? Get(map, "set").
-    Value adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map);
-    // If IsCallable(adder) is false, throw a TypeError exception.
-    if (!adder.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
-    }
-
-    // Let iteratorRecord be ? GetIterator(iterable).
-    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
-    while (true) {
-        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
-        if (!next.hasValue()) {
-            return map;
-        }
-
-        Value nextItem = IteratorObject::iteratorValue(state, next.value());
-        if (!nextItem.isObject()) {
-            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
-            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
-        }
-
-        try {
-            // Let k be Get(nextItem, "0").
-            // If k is an abrupt completion, return ? IteratorClose(iter, k).
-            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
-            // Let v be Get(nextItem, "1").
-            // If v is an abrupt completion, return ? IteratorClose(iter, v).
-            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
-
-            // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »).
-            Value argv[2] = { k, v };
-            Object::call(state, adder, map, 2, argv);
-        } catch (const Value& v) {
-            // we should save thrown value bdwgc cannot track thrown value
-            Value exceptionValue = v;
-            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
-            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-        }
-    }
-
-    return map;
-}
-
-#define RESOLVE_THIS_BINDING_TO_MAP(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                          \
-    if (!thisValue.isObject() || !thisValue.asObject()->isMapObject()) {                                                                                                                                                                                 \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                    \
-    MapObject* NAME = thisValue.asObject()->asMapObject();
-
-static Value builtinMapClear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, clear);
-    M->clear(state);
-    return Value();
-}
-
-static Value builtinMapDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, stringDelete);
-    return Value(M->deleteOperation(state, argv[0]));
-}
-
-static Value builtinMapGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, get);
-    return M->get(state, argv[0]);
-}
-
-static Value builtinMapHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, has);
-    return Value(M->has(state, argv[0]));
-}
-
-static Value builtinMapSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, set);
-    M->set(state, argv[0], argv[1]);
-    return M;
-}
-
-static Value builtinMapForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, forEach);
-    // Let M be the this value.
-    // If Type(M) is not Object, throw a TypeError exception.
-    // If M does not have a [[MapData]] internal slot, throw a TypeError exception.
-
-    Value callbackfn = argv[0];
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Map.string(), true, state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc >= 2) {
-        T = argv[1];
-    }
-    // Let entries be the List that is the value of M's [[MapData]] internal slot.
-    const MapObject::MapObjectData& entries = M->storage();
-    // Repeat for each Record {[[Key]], [[Value]]} e that is an element of entries, in original key insertion order
-    for (size_t i = 0; i < entries.size(); i++) {
-        // If e.[[Key]] is not empty, then
-        if (!entries[i].first.isEmpty()) {
-            // Perform ? Call(callbackfn, T, « e.[[Value]], e.[[Key]], M »).
-            Value argv[3] = { Value(entries[i].second), Value(entries[i].first), Value(M) };
-            Object::call(state, callbackfn, T, 3, argv);
-        }
-    }
-
-    return Value();
-}
-
-static Value builtinMapKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, keys);
-    return M->keys(state);
-}
-
-static Value builtinMapValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, values);
-    return M->values(state);
-}
-
-static Value builtinMapEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, entries);
-    return M->entries(state);
-}
-
-static Value builtinMapSizeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_MAP(M, Map, size);
-    return Value(M->size(state));
-}
-
-static Value builtinMapIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isMapIteratorObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().MapIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    MapIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asMapIteratorObject();
-    return iter->next(state);
-}
-
-void GlobalObject::installMap(ExecutionState& state)
-{
-    m_map = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Map, builtinMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_map->setGlobalIntrinsicObject(state);
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_map->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    m_mapPrototype = new MapObject(state, m_objectPrototype);
-    m_mapPrototype->setGlobalIntrinsicObject(state, true);
-    m_mapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clear),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinMapClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinMapDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinMapGet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinMapHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinMapSet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinMapForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keys, builtinMapKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinMapValues, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    auto entFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinMapEntries, 0, NativeFunctionInfo::Strict));
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
-                                                     ObjectPropertyDescriptor(entFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                     ObjectPropertyDescriptor(entFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                     ObjectPropertyDescriptor(Value(state.context()->staticStrings().Map.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    JSGetterSetter gs(
-        new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSize, builtinMapSizeGetter, 0, NativeFunctionInfo::Strict)),
-        Value(Value::EmptyValue));
-    ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-    m_mapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);
-
-    m_mapIteratorPrototype = new Object(state, m_iteratorPrototype);
-    m_mapIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_mapIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinMapIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_mapIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                             ObjectPropertyDescriptor(Value(String::fromASCII("Map Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    m_map->setFunctionPrototype(state, m_mapPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Map),
-                      ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinMath.cpp
deleted file mode 100644 (file)
index f4b629f..0000000
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "StringObject.h"
-#include "NativeFunctionObject.h"
-
-#include "IEEE754.h"
-#include <math.h>
-
-namespace Escargot {
-
-static Value builtinMathAbs(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return Value(std::abs(argv[0].toNumber(state)));
-}
-
-static Value builtinMathMax(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    bool is_NaN = false;
-    if (argc == 0) {
-        double n_inf = -1 * std::numeric_limits<double>::infinity();
-        return Value(n_inf);
-    }
-
-    double maxValue = argv[0].toNumber(state);
-    for (unsigned i = 1; i < argc; i++) {
-        double value = argv[i].toNumber(state);
-        if (std::isnan(value))
-            is_NaN = true;
-        if (value > maxValue || (!value && !maxValue && !std::signbit(value)))
-            maxValue = value;
-    }
-    if (is_NaN) {
-        double qnan = std::numeric_limits<double>::quiet_NaN();
-        return Value(qnan);
-    }
-    return Value(maxValue);
-}
-
-static Value builtinMathMin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (argc == 0) {
-        return Value(std::numeric_limits<double>::infinity());
-    }
-
-    bool hasNaN = false;
-    double minValue = argv[0].toNumber(state);
-    for (unsigned i = 1; i < argc; i++) {
-        double value = argv[i].toNumber(state);
-        if (std::isnan(value)) {
-            hasNaN = true;
-        }
-        if (value < minValue || (!value && !minValue && std::signbit(value))) {
-            minValue = value;
-        }
-    }
-    if (hasNaN) {
-        double qnan = std::numeric_limits<double>::quiet_NaN();
-        return Value(qnan);
-    }
-    return Value(minValue);
-}
-
-static Value builtinMathRound(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    if (x == static_cast<int64_t>(x)) {
-        return Value(x);
-    }
-    if (x == -0.5)
-        return Value(-0.0);
-    else if (x > -0.5)
-        return Value(round(x));
-    else
-        return Value(floor(x + 0.5));
-}
-
-static Value builtinMathSin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value x = argv[0];
-    return Value(ieee754::sin(x.toNumber(state)));
-}
-
-static Value builtinMathSinh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::sinh(x));
-}
-
-static Value builtinMathCos(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value x = argv[0];
-    return Value(ieee754::cos(x.toNumber(state)));
-}
-
-static Value builtinMathCosh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::cosh(x));
-}
-
-static Value builtinMathAcos(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::acos(x));
-}
-
-static Value builtinMathAcosh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::acosh(x));
-}
-
-static Value builtinMathAsin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::asin(x));
-}
-
-static Value builtinMathAsinh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::asinh(x));
-}
-
-static Value builtinMathAtan(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::atan(x));
-}
-
-static Value builtinMathAtan2(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double y = argv[0].toNumber(state);
-    double x = argv[1].toNumber(state);
-    return Value(ieee754::atan2(y, x));
-}
-
-static Value builtinMathAtanh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::atanh(x));
-}
-
-static Value builtinMathTan(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::tan(x));
-}
-
-static Value builtinMathTanh(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::tanh(x));
-}
-
-static Value builtinMathTrunc(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(trunc(x));
-}
-
-static Value builtinMathSign(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    if (std::isnan(x))
-        return Value(std::numeric_limits<double>::quiet_NaN());
-    else if (x == 0.0) {
-        if (std::signbit(x)) {
-            return Value(Value::EncodeAsDouble, -0.0);
-        } else {
-            return Value(0);
-        }
-    } else if (std::signbit(x))
-        return Value(-1);
-    else
-        return Value(1);
-}
-
-static Value builtinMathSqrt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value x = argv[0];
-    return Value(sqrt(x.toNumber(state)));
-}
-
-static Value builtinMathPow(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    double y = argv[1].toNumber(state);
-    if (UNLIKELY(std::isnan(y)))
-        return Value(std::numeric_limits<double>::quiet_NaN());
-    if (UNLIKELY(std::abs(x) == 1 && std::isinf(y)))
-        return Value(std::numeric_limits<double>::quiet_NaN());
-
-    int y_int = static_cast<int>(y);
-
-    if (y == y_int) {
-        unsigned n = (y < 0) ? -y : y;
-        double m = x;
-        double p = 1;
-        while (true) {
-            if ((n & 1) != 0)
-                p *= m;
-            n >>= 1;
-            if (n == 0) {
-                if (y < 0) {
-                    // Unfortunately, we have to be careful when p has reached
-                    // infinity in the computation, because sometimes the higher
-                    // internal precision in the pow() implementation would have
-                    // given us a finite p. This happens very rarely.
-
-                    double result = 1.0 / p;
-                    return (result == 0 && std::isinf(p)) ? Value(pow(x, static_cast<double>(y))) // Avoid pow(double, int).
-                                                          : Value(result);
-                }
-
-                return Value(p);
-            }
-            m *= m;
-        }
-    }
-
-    if (std::isinf(x)) {
-        if (x > 0) {
-            if (y > 0) {
-                return Value(std::numeric_limits<double>::infinity());
-            } else {
-                return Value(0.0);
-            }
-        } else {
-            if (y > 0) {
-                if (y == y_int && y_int % 2) { // odd
-                    return Value(-std::numeric_limits<double>::infinity());
-                } else {
-                    return Value(std::numeric_limits<double>::infinity());
-                }
-            } else {
-                if (y == y_int && y_int % 2) {
-                    return Value(-0.0);
-                } else {
-                    return Value(0.0);
-                }
-            }
-        }
-    }
-    // x == -0
-    if (1 / x == -std::numeric_limits<double>::infinity()) {
-        // y cannot be an odd integer because the case is filtered by "if (y_int == y)" above
-        if (y > 0) {
-            return Value(0);
-        } else if (y < 0) {
-            return Value(std::numeric_limits<double>::infinity());
-        }
-    }
-
-    if (y == 0.5) {
-        return Value(sqrt(x));
-    } else if (y == -0.5) {
-        return Value(1.0 / sqrt(x));
-    }
-
-    return Value(pow(x, y));
-}
-
-static Value builtinMathCbrt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::cbrt(x));
-}
-
-static Value builtinMathCeil(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-
-    // I add custom ceil implementation
-    // because I found some problem from gcc implementation about negative zero
-    return Value(ieee754::ceil(x));
-}
-
-static Value builtinMathClz32(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    uint32_t x = argv[0].toUint32(state);
-    int clz32 = 0;
-    for (int i = 31; i >= 0; i--) {
-        if (!(x >> i))
-            clz32++;
-        else
-            break;
-    }
-    return Value(clz32);
-}
-
-static Value builtinMathFloor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(floor(x));
-}
-
-static Value builtinMathFround(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(static_cast<double>(static_cast<float>(x)));
-}
-
-static Value builtinMathHypot(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double maxValue = 0;
-    bool has_nan = false;
-    bool has_inf = false;
-    for (unsigned i = 0; i < argc; i++) {
-        double value = argv[i].toNumber(state);
-        if (std::isinf(value)) {
-            has_inf = true;
-        } else if (std::isnan(value)) {
-            has_nan = true;
-        }
-        double absValue = std::abs(value);
-        maxValue = std::max(maxValue, absValue);
-    }
-    if (has_inf) {
-        return Value(std::numeric_limits<double>::infinity());
-    }
-
-    if (has_nan) {
-        double qnan = std::numeric_limits<double>::quiet_NaN();
-        return Value(qnan);
-    }
-
-    if (maxValue == 0) {
-        return Value(0.0);
-    }
-
-    double sum = 0;
-    double compensation = 0;
-    for (unsigned i = 0; i < argc; i++) {
-        double value = argv[i].toNumber(state);
-        double scaledArgument = value / maxValue;
-        double summand = scaledArgument * scaledArgument - compensation;
-        double preliminary = sum + summand;
-        compensation = (preliminary - sum) - summand;
-        sum = preliminary;
-    }
-    return Value(std::sqrt(sum) * maxValue);
-}
-
-static Value builtinMathIMul(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    int32_t x = argv[0].toInt32(state);
-    int32_t y = argv[1].toInt32(state);
-    return Value(x * y);
-}
-
-static Value builtinMathLog(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::log(x));
-}
-
-static Value builtinMathLog1p(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::log1p(x));
-}
-
-static Value builtinMathLog10(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::log10(x));
-}
-
-static Value builtinMathLog2(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::log2(x));
-}
-
-static Value builtinMathRandom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    std::uniform_real_distribution<double> distribution;
-    return Value(distribution(VMInstance::randEngine()));
-}
-
-static Value builtinMathExp(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::exp(x));
-}
-
-static Value builtinMathExpm1(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double x = argv[0].toNumber(state);
-    return Value(ieee754::expm1(x));
-}
-
-void GlobalObject::installMath(ExecutionState& state)
-{
-    m_math = new Object(state);
-    m_math->setGlobalIntrinsicObject(state);
-
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                             ObjectPropertyDescriptor(Value(state.context()->staticStrings().Math.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // initialize math object: $20.2.1.6 Math.PI
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_math->defineOwnPropertyThrowsException(state, strings->PI, ObjectPropertyDescriptor(Value(3.1415926535897932), ObjectPropertyDescriptor::ValuePresent));
-    // TODO(add reference)
-    m_math->defineOwnPropertyThrowsException(state, strings->E, ObjectPropertyDescriptor(Value(2.718281828459045), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.3
-    m_math->defineOwnPropertyThrowsException(state, strings->LN2, ObjectPropertyDescriptor(Value(0.6931471805599453), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.2
-    m_math->defineOwnPropertyThrowsException(state, strings->LN10, ObjectPropertyDescriptor(Value(2.302585092994046), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.4
-    m_math->defineOwnPropertyThrowsException(state, strings->LOG2E, ObjectPropertyDescriptor(Value(1.4426950408889634), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.5
-    m_math->defineOwnPropertyThrowsException(state, strings->LOG10E, ObjectPropertyDescriptor(Value(0.4342944819032518), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.7
-    m_math->defineOwnPropertyThrowsException(state, strings->SQRT1_2, ObjectPropertyDescriptor(Value(0.7071067811865476), ObjectPropertyDescriptor::ValuePresent));
-    // http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1.8
-    m_math->defineOwnPropertyThrowsException(state, strings->SQRT2, ObjectPropertyDescriptor(Value(1.4142135623730951), ObjectPropertyDescriptor::ValuePresent));
-
-    // initialize math object: $20.2.2.1 Math.abs()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().abs),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().abs, builtinMathAbs, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.2 Math.acos()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().acos),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().acos, builtinMathAcos, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.3 Math.acosh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().acosh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().acosh, builtinMathAcosh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.4 Math.asin()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().asin),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asin, builtinMathAsin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.5 Math.asinh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().asinh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().asinh, builtinMathAsinh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.6 Math.atan()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atan),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atan, builtinMathAtan, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.7 Math.atanh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atanh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atanh, builtinMathAtanh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.8 Math.atan2()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().atan2),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().atan2, builtinMathAtan2, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.9 Math.cbrt()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cbrt),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cbrt, builtinMathCbrt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.10 Math.ceil()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().ceil),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().ceil, builtinMathCeil, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.11 Math.clz32()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clz32),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clz32, builtinMathClz32, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.12 Math.cos()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cos),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cos, builtinMathCos, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.13 Math.cosh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().cosh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cosh, builtinMathCosh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.14 Math.exp()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().exp),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().exp, builtinMathExp, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.15 Math.expm1()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().expm1),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().expm1, builtinMathExpm1, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.16 Math.floor()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().floor),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().floor, builtinMathFloor, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.17 Math.fround()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().fround),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().fround, builtinMathFround, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.18 Math.hypot()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().hypot),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().hypot, builtinMathHypot, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.19 Math.imul()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().imul),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().imul, builtinMathIMul, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // initialize math object: $20.2.2.20 Math.log()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log, builtinMathLog, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.21 Math.log1p()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log1p),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log1p, builtinMathLog1p, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.22 Math.log10()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log10),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log10, builtinMathLog10, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.23 Math.log2()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().log2),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().log2, builtinMathLog2, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.24 Math.max()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().max),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().max, builtinMathMax, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.25 Math.min()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().min),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().min, builtinMathMin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.26 Math.pow()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().pow),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().pow, builtinMathPow, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.27 Math.random()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().random),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().random, builtinMathRandom, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.28 Math.round()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().round),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().round, builtinMathRound, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.29 Math.sign()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sign),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sign, builtinMathSign, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.30 Math.sin()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sin),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sin, builtinMathSin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.31 Math.sinh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sinh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sinh, builtinMathSinh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.32 Math.sqrt()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().sqrt),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().sqrt, builtinMathSqrt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.33 Math.tan()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().tan),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().tan, builtinMathTan, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.34 Math.tanh()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().tanh),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().tanh, builtinMathTanh, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // initialize math object: $20.2.2.35 Math.trunc()
-    m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().trunc),
-                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().trunc, builtinMathTrunc, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Math),
-                      ObjectPropertyDescriptor(m_math, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinNumber.cpp
deleted file mode 100644 (file)
index cd01cba..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "NumberObject.h"
-#include "NativeFunctionObject.h"
-
-// dtoa
-#include "ieee.h"
-#include "double-conversion.h"
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#include "IntlNumberFormat.h"
-#endif
-
-#define NUMBER_TO_STRING_BUFFER_LENGTH 128
-
-namespace Escargot {
-
-static int itoa(int64_t value, char* sp, int radix)
-{
-    char tmp[256]; // be careful with the length of the buffer
-    char* tp = tmp;
-    int i;
-    uint64_t v;
-
-    int sign = (radix == 10 && value < 0);
-    if (sign) {
-        v = -value;
-    } else {
-        v = (uint64_t)value;
-    }
-
-    while (v || tp == tmp) {
-        i = v % radix;
-        v /= radix; // v/=radix uses less CPU clocks than v=v/radix does
-        if (i < 10) {
-            *tp++ = i + '0';
-        } else {
-            *tp++ = i + 'a' - 10;
-        }
-    }
-
-    int64_t len = tp - tmp;
-
-    if (sign) {
-        *sp++ = '-';
-        len++;
-    }
-
-    while (tp > tmp) {
-        *sp++ = *--tp;
-    }
-    *sp++ = 0;
-
-    return len;
-}
-
-static Value builtinNumberConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double num = 0;
-    if (argc > 0) {
-        if (UNLIKELY(argv[0].isBigInt())) {
-            num = argv[0].asBigInt()->toNumber();
-        } else {
-            num = argv[0].toNumber(state);
-        }
-    }
-
-    if (!newTarget.hasValue()) {
-        return Value(num);
-    } else {
-        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-            return constructorRealm->globalObject()->numberPrototype();
-        });
-        NumberObject* numObj = new NumberObject(state, proto, num);
-        return numObj;
-    }
-}
-
-static Value builtinNumberToFixed(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double number = 0.0;
-
-    if (thisValue.isNumber()) {
-        number = thisValue.asNumber();
-    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
-        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toFixed.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-
-    Value fractionDigits = argv[0];
-    int digit = fractionDigits.toInteger(state);
-    if (digit < 0 || digit > 100) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toFixed.string(), ErrorObject::Messages::GlobalObject_RangeError);
-    }
-
-    if (std::isnan(number)) {
-        return state.context()->staticStrings().NaN.string();
-    }
-
-    if (std::isinf(number)) {
-        if (number < 0) {
-            return state.context()->staticStrings().NegativeInfinity.string();
-        } else {
-            return state.context()->staticStrings().Infinity.string();
-        }
-    }
-
-    if (std::abs(number) >= pow(10, 21)) {
-        return Value(number).toString(state);
-    }
-
-    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
-    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
-    double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToFixed(number, digit, &builder);
-    return Value(new ASCIIString(builder.Finalize()));
-}
-
-static Value builtinNumberToExponential(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double number = 0.0;
-
-    if (thisValue.isNumber()) {
-        number = thisValue.asNumber();
-    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
-        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toExponential.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-
-    Value fractionDigits = argv[0];
-    int digit = fractionDigits.toInteger(state);
-
-    if (std::isnan(number)) { // 3
-        return state.context()->staticStrings().NaN.string();
-    }
-
-    if (std::isinf(number)) { // 6
-        if (number < 0) {
-            return state.context()->staticStrings().NegativeInfinity.string();
-        } else {
-            return state.context()->staticStrings().Infinity.string();
-        }
-    }
-
-    if (digit < 0 || digit > 100) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toExponential.string(), ErrorObject::Messages::GlobalObject_RangeError);
-    }
-
-    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
-    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
-    if (fractionDigits.isUndefined()) {
-        double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(number, -1, &builder);
-    } else {
-        double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(number, digit, &builder);
-    }
-    return Value(new ASCIIString(builder.Finalize()));
-}
-
-static Value builtinNumberToPrecision(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double number = 0.0;
-
-    if (thisValue.isNumber()) {
-        number = thisValue.asNumber();
-    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
-        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toPrecision.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-
-    Value precision = argv[0];
-    if (precision.isUndefined()) {
-        return Value(number).toString(state);
-    }
-
-    int p = precision.toInteger(state);
-
-    if (std::isnan(number)) {
-        return state.context()->staticStrings().NaN.string();
-    }
-
-    if (std::isinf(number)) {
-        if (number < 0) {
-            return state.context()->staticStrings().NegativeInfinity.string();
-        } else {
-            return state.context()->staticStrings().Infinity.string();
-        }
-    }
-
-    if (p < 1 || p > 100) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toPrecision.string(), ErrorObject::Messages::GlobalObject_RangeError);
-    }
-
-    char buffer[NUMBER_TO_STRING_BUFFER_LENGTH];
-    double_conversion::StringBuilder builder(buffer, NUMBER_TO_STRING_BUFFER_LENGTH);
-    double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(number, p, &builder);
-    return Value(new ASCIIString(builder.Finalize()));
-}
-
-static Value builtinNumberToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    double number = 0.0;
-
-    if (thisValue.isNumber()) {
-        number = thisValue.asNumber();
-    } else if (thisValue.isPointerValue() && thisValue.asPointerValue()->isNumberObject()) {
-        number = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-
-    double radix = 10;
-    if (argc > 0 && !argv[0].isUndefined()) {
-        radix = argv[0].toInteger(state);
-        if (radix < 2 || radix > 36) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_RadixInvalidRange);
-        }
-    }
-    if (std::isnan(number) || std::isinf(number)) {
-        return Value(number).toString(state);
-    }
-    if (radix == 10) {
-        return Value(number).toString(state);
-    }
-
-    bool isInteger = (static_cast<int64_t>(number) == number);
-    if (isInteger) {
-        bool minusFlag = (number < 0) ? 1 : 0;
-        number = (number < 0) ? (-1 * number) : number;
-        char buffer[256];
-        if (minusFlag) {
-            buffer[0] = '-';
-            itoa(static_cast<int64_t>(number), &buffer[1], radix);
-        } else {
-            itoa(static_cast<int64_t>(number), buffer, radix);
-        }
-        return new ASCIIString(buffer);
-    } else {
-        ASSERT(Value(number).isDouble());
-        NumberObject::RadixBuffer s;
-        const char* str = NumberObject::toStringWithRadix(state, s, number, radix);
-        return new ASCIIString(str);
-    }
-}
-
-static Value builtinNumberToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Number, toLocaleString);
-    if (!thisObject->isNumberObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    Value locales = argc > 0 ? argv[0] : Value();
-    Value options = argc > 1 ? argv[1] : Value();
-    Object* numberFormat = IntlNumberFormat::create(state, state.context(), locales, options);
-    double x = 0;
-    if (thisValue.isNumber()) {
-        x = thisValue.asNumber();
-    } else if (thisValue.isObject() && thisValue.asObject()->isNumberObject()) {
-        x = thisValue.asPointerValue()->asNumberObject()->primitiveValue();
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    }
-    auto result = IntlNumberFormat::format(state, numberFormat, x);
-
-    return new UTF16String(result.data(), result.length());
-#else
-
-    ObjectGetResult toStrFuncGetResult = thisObject->get(state, ObjectPropertyName(state.context()->staticStrings().toString));
-    if (toStrFuncGetResult.hasValue()) {
-        Value toStrFunc = toStrFuncGetResult.value(state, thisObject);
-        if (toStrFunc.isCallable()) {
-            // toLocaleString() ignores the first argument, unlike toString()
-            return Object::call(state, toStrFunc, thisObject, 0, argv);
-        }
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Number.string(), true, state.context()->staticStrings().toLocaleString.string(), ErrorObject::Messages::GlobalObject_ToLocaleStringNotCallable);
-    RELEASE_ASSERT_NOT_REACHED();
-    return Value();
-#endif
-}
-
-static Value builtinNumberValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isNumber()) {
-        return Value(thisValue);
-    } else if (thisValue.isObject() && thisValue.asObject()->isNumberObject()) {
-        return Value(thisValue.asPointerValue()->asNumberObject()->primitiveValue());
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotNumber);
-    RELEASE_ASSERT_NOT_REACHED();
-    return Value();
-}
-
-static Value builtinNumberIsFinite(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isNumber()) {
-        return Value(Value::False);
-    }
-
-    double number = argv[0].asNumber();
-    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
-        return Value(Value::False);
-    }
-    return Value(Value::True);
-}
-
-static Value builtinNumberIsInteger(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isNumber()) {
-        return Value(Value::False);
-    }
-
-    double number = argv[0].asNumber();
-    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
-        return Value(Value::False);
-    }
-
-    double integer = argv[0].toInteger(state);
-    if (number != integer) {
-        return Value(Value::False);
-    }
-    return Value(Value::True);
-}
-
-static Value builtinNumberIsNaN(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isNumber()) {
-        return Value(Value::False);
-    }
-
-    double number = argv[0].asNumber();
-    if (std::isnan(number)) {
-        return Value(Value::True);
-    }
-    return Value(Value::False);
-}
-
-static Value builtinNumberIsSafeInteger(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isNumber()) {
-        return Value(Value::False);
-    }
-
-    double number = argv[0].asNumber();
-    if (std::isnan(number) || number == std::numeric_limits<double>::infinity() || number == -std::numeric_limits<double>::infinity()) {
-        return Value(Value::False);
-    }
-
-    double integer = argv[0].toInteger(state);
-    if (number != integer) {
-        return Value(Value::False);
-    }
-
-    if (std::abs(integer) <= 9007199254740991.0) {
-        return Value(Value::True);
-    }
-    return Value(Value::False);
-}
-
-void GlobalObject::installNumber(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_number = new NativeFunctionObject(state, NativeFunctionInfo(strings->Number, builtinNumberConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_number->setGlobalIntrinsicObject(state);
-
-    m_numberPrototype = new NumberObject(state, m_objectPrototype, 0);
-    m_numberPrototype->setGlobalIntrinsicObject(state, true);
-    m_number->setFunctionPrototype(state, m_numberPrototype);
-
-    m_numberPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinNumberToString, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleString),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleString, builtinNumberToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toFixed),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toFixed, builtinNumberToFixed, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toExponential),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toExponential, builtinNumberToExponential, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toPrecision),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toPrecision, builtinNumberToPrecision, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $20.1.3.26 Number.prototype.valueOf
-    m_numberPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinNumberValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    m_number->setFunctionPrototype(state, m_numberPrototype);
-
-    ObjectPropertyDescriptor::PresentAttribute allFalsePresent = (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent
-                                                                                                              | ObjectPropertyDescriptor::NonEnumerablePresent
-                                                                                                              | ObjectPropertyDescriptor::NonConfigurablePresent);
-
-    // $20.1.2.1 Number.EPSILON
-    m_number->defineOwnPropertyThrowsException(state, strings->EPSILON, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::epsilon()), allFalsePresent));
-    // $20.1.2.2 Number.isFinite
-    m_number->defineOwnPropertyThrowsException(state, strings->isFinite,
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isFinite, builtinNumberIsFinite, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $20.1.2.3 Number.isInteger
-    m_number->defineOwnPropertyThrowsException(state, strings->isInteger,
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isInteger, builtinNumberIsInteger, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $20.1.2.3 Number.isNaN
-    m_number->defineOwnPropertyThrowsException(state, strings->isNaN,
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isNaN, builtinNumberIsNaN, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $20.1.2.5 Number.isSafeInteger
-    m_number->defineOwnPropertyThrowsException(state, strings->isSafeInteger,
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isSafeInteger, builtinNumberIsSafeInteger, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $20.1.2.6 Number.MAX_SAFE_INTEGER
-    m_number->defineOwnPropertyThrowsException(state, strings->MAX_SAFE_INTEGER, ObjectPropertyDescriptor(Value(9007199254740991.0), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
-    // $20.1.2.7 Number.MAX_VALUE
-    m_number->defineOwnPropertyThrowsException(state, strings->MAX_VALUE, ObjectPropertyDescriptor(Value(1.7976931348623157E+308), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
-    // $20.1.2.8 Number.MIN_SAFE_INTEGER
-    m_number->defineOwnPropertyThrowsException(state, strings->MIN_SAFE_INTEGER, ObjectPropertyDescriptor(Value(-9007199254740991.0), (ObjectPropertyDescriptor::PresentAttribute)allFalsePresent));
-    // $20.1.2.9 Number.MIN_VALUE
-    m_number->defineOwnPropertyThrowsException(state, strings->MIN_VALUE, ObjectPropertyDescriptor(Value(5E-324), allFalsePresent));
-    // $20.1.2.10 Number.NaN
-    m_number->defineOwnPropertyThrowsException(state, strings->NaN, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::quiet_NaN()), allFalsePresent));
-    // $20.1.2.11 Number.NEGATIVE_INFINITY
-    m_number->defineOwnPropertyThrowsException(state, strings->NEGATIVE_INFINITY, ObjectPropertyDescriptor(Value(-std::numeric_limits<double>::infinity()), allFalsePresent));
-    // $20.1.2.14 Number.POSITIVE_INFINITY
-    m_number->defineOwnPropertyThrowsException(state, strings->POSITIVE_INFINITY, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::infinity()), allFalsePresent));
-
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Number),
-                      ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinObject.cpp
deleted file mode 100644 (file)
index f9c1de4..0000000
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "ArrayObject.h"
-#include "NativeFunctionObject.h"
-#include "IteratorObject.h"
-
-namespace Escargot {
-
-typedef VectorWithInlineStorage<48, std::pair<ObjectPropertyName, ObjectStructurePropertyDescriptor>, GCUtil::gc_malloc_allocator<std::pair<ObjectPropertyName, ObjectStructurePropertyDescriptor>>> ObjectStructurePropertyVector;
-
-static Value builtinObject__proto__Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return thisValue.toObject(state)->getPrototype(state);
-}
-
-static Value builtinObject__proto__Setter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value value = argv[0];
-    Object* thisObject = thisValue.toObject(state);
-    // Setting __proto__ to a non-object, non-null value is ignored
-    if (!value.isObject() && !value.isNull()) {
-        return Value();
-    }
-    if (!thisObject->setPrototype(state, value)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "can't set prototype of this object");
-    }
-    return Value();
-}
-
-static Value builtinObjectConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is neither undefined nor the active function, then
-    if (newTarget.hasValue() && newTarget.value() != state.resolveCallee()) {
-        // Return ? OrdinaryCreateFromConstructor(NewTarget, "%ObjectPrototype%").
-        Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-            return constructorRealm->globalObject()->objectPrototype();
-        });
-        return new Object(state, proto);
-    }
-
-    Value value = argv[0];
-    if (value.isUndefined() || value.isNull()) {
-        // If value is null, undefined or not supplied, return ObjectCreate(%ObjectPrototype%).
-        return new Object(state);
-    } else {
-        // Return ! ToObject(value).
-        return value.toObject(state);
-    }
-}
-
-static Value builtinObjectValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(ret, Object, valueOf);
-    return ret;
-}
-
-static Value builtinObjectPreventExtensions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return argv[0];
-    }
-    Object* o = argv[0].asObject();
-    if (!o->preventExtensions(state)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().preventExtensions.string(), "PreventExtensions is false");
-    }
-    return o;
-}
-
-static Value builtinObjectToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    StaticStrings* strings = &state.context()->staticStrings();
-
-    if (thisValue.isUndefined()) {
-        return strings->lazyObjectUndefinedToString().string();
-    } else if (thisValue.isNull()) {
-        return strings->lazyObjectNullToString().string();
-    }
-
-    Object* thisObject = thisValue.toObject(state);
-
-    // check isArray first
-    bool isArray = thisObject->isArray(state);
-
-    Value toStringTag = thisObject->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag)).value(state, thisObject);
-    if (toStringTag.isString()) {
-        String* tag = toStringTag.asString();
-        auto bad = tag->bufferAccessData();
-        if (bad.has8BitContent && bad.length < 256) {
-            LChar* buf = (LChar*)alloca(bad.length + 10);
-            size_t len = 0;
-
-            buf[0] = '[';
-            buf[1] = 'o';
-            buf[2] = 'b';
-            buf[3] = 'j';
-            buf[4] = 'e';
-            buf[5] = 'c';
-            buf[6] = 't';
-            buf[7] = ' ';
-            memcpy(buf + 8, bad.bufferAs8Bit, bad.length);
-            buf[bad.length + 8] = ']';
-            buf[bad.length + 9] = 0;
-            len = 9 + bad.length;
-
-            return AtomicString(state.context(), buf, len).string();
-        }
-
-        StringBuilder builder;
-        builder.appendString("[object ");
-        builder.appendString(tag);
-        builder.appendString("]");
-        return AtomicString(state, builder.finalize()).string();
-    }
-
-    if (isArray) {
-        return strings->lazyObjectArrayToString().string();
-    } else if (thisObject->isArgumentsObject()) {
-        return strings->lazyObjectArgumentsToString().string();
-    } else if (thisObject->isCallable()) {
-        return strings->lazyObjectFunctionToString().string();
-    } else if (thisObject->isErrorObject()) {
-        return strings->lazyObjectErrorToString().string();
-    } else if (thisObject->isBooleanObject()) {
-        return strings->lazyObjectBooleanToString().string();
-    } else if (thisObject->isNumberObject()) {
-        return strings->lazyObjectNumberToString().string();
-    } else if (thisObject->isStringObject()) {
-        return strings->lazyObjectStringToString().string();
-    } else if (thisObject->isDateObject()) {
-        return strings->lazyObjectDateToString().string();
-    } else if (thisObject->isRegExpObject()) {
-        return strings->lazyObjectRegExpToString().string();
-    }
-
-    return strings->lazyObjectObjectToString().string();
-}
-
-static Value builtinObjectHasOwnProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value key = argv[0].toPrimitive(state, Value::PrimitiveTypeHint::PreferString);
-    Object* obj = thisValue.toObject(state);
-    return Value(obj->hasOwnProperty(state, ObjectPropertyName(state, key)));
-}
-
-static Value objectDefineProperties(ExecutionState& state, Value object, Value properties)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    if (!object.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Object.string(), false, strings->defineProperty.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObject);
-    }
-
-    Object* O = object.asObject();
-    // Let props be ? ToObject(Properties).
-    Object* props = properties.toObject(state);
-
-    // Let keys be ? props.[[OwnPropertyKeys]]().
-    Object::OwnPropertyKeyVector keys = props->ownPropertyKeys(state);
-    // Let descriptors be a new empty List.
-    VectorWithInlineStorage<32, std::pair<ObjectPropertyName, ObjectPropertyDescriptor>, GCUtil::gc_malloc_allocator<std::pair<ObjectPropertyName, ObjectPropertyDescriptor>>> descriptors;
-
-    for (size_t i = 0; i < keys.size(); i++) {
-        // Let propDesc be ? props.[[GetOwnProperty]](nextKey).
-        ObjectPropertyName nextKey(state, keys[i]);
-        ObjectGetResult propDesc = props->getOwnProperty(state, nextKey);
-        // If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
-        if (propDesc.hasValue() && propDesc.isEnumerable()) {
-            // Let descObj be ? Get(props, nextKey).
-            Value descVal = propDesc.value(state, props);
-            if (!descVal.isObject()) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().defineProperty.string(), ErrorObject::Messages::GlobalObject_DescriptorNotObject);
-            }
-
-            // Let desc be ? ToPropertyDescriptor(descObj).
-            ObjectPropertyDescriptor desc(state, descVal.asObject());
-            // Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
-            descriptors.push_back(std::make_pair(nextKey, desc));
-        }
-    }
-
-    // For each pair from descriptors in list order, do
-    for (auto it : descriptors) {
-        // Let P be the first element of pair.
-        // Let desc be the second element of pair.
-        // Perform ? DefinePropertyOrThrow(O, P, desc).
-        O->defineOwnPropertyThrowsException(state, it.first, it.second);
-    }
-
-    return O;
-}
-
-static Value builtinObjectCreate(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject() && !argv[0].isNull())
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().create.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObjectAndNotNull);
-    Object* obj = new Object(state);
-    if (argv[0].isNull())
-        obj->setPrototype(state, Value(Value::Null));
-    else
-        obj->setPrototype(state, argv[0]);
-
-    if (!argv[1].isUndefined())
-        return objectDefineProperties(state, obj, argv[1]);
-    return obj;
-}
-
-static Value builtinObjectDefineProperties(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return objectDefineProperties(state, argv[0], argv[1]);
-}
-
-static Value builtinObjectDefineProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Object.defineProperty ( O, P, Attributes )
-    // If Type(O) is not Object, throw a TypeError exception.
-    if (!argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().defineProperty.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotObject);
-    }
-    Object* O = argv[0].asObject();
-
-    // Let key be ToPropertyKey(P).
-    ObjectPropertyName key = ObjectPropertyName(state, argv[1]);
-
-    // Let desc be ToPropertyDescriptor(Attributes).
-    if (!argv[2].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Property description must be an object");
-    }
-
-    ObjectPropertyDescriptor desc(state, argv[2].asObject());
-
-    O->defineOwnPropertyThrowsException(state, key, desc);
-    return O;
-}
-
-static Value builtinObjectIsPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Object.prototype.isPrototypeOf (V)
-    // If V is not an object, return false.
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-    Value V = argv[0];
-
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, isPrototypeOf);
-
-    // Repeat
-    while (true) {
-        // Let V be the value of the [[Prototype]] internal property of V.
-        V = V.toObject(state)->getPrototype(state);
-        // if V is null, return false
-        if (!V.isObject())
-            return Value(false);
-        // If O and V refer to the same object, return true.
-        if (V.asObject() == O) {
-            return Value(true);
-        }
-    }
-}
-
-static Value builtinObjectPropertyIsEnumerable(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let P be toPropertyKey(V).
-    Value P = argv[0].toPropertyKey(state);
-
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, propertyIsEnumerable);
-
-    // Let desc be the result of calling the [[GetOwnProperty]] internal method of O with argument name.
-    ObjectGetResult desc = O->getOwnProperty(state, ObjectPropertyName(state, P));
-
-    // If desc is undefined, return false.
-    if (!desc.hasValue())
-        return Value(false);
-
-    // Return the value of desc.[[Enumerable]].
-    return Value(desc.isEnumerable());
-}
-
-static Value builtinObjectToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/#sec-object.prototype.tolocalestring
-    // Let O be the this value.
-    // Return ? Invoke(O, "toString").
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, Object, toLocaleString);
-    Value toString = O->get(state, ObjectPropertyName(state.context()->staticStrings().toString)).value(state, thisValue);
-    return Object::call(state, toString, thisValue, 0, nullptr);
-}
-
-static Value builtinObjectGetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return argv[0].toObject(state)->getPrototype(state);
-}
-
-static Value builtinObjectSetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
-    // 19.1.2.18 Object.setPrototypeOf ( O, proto )
-    Value object = argv[0];
-    Value proto = argv[1];
-
-    // 1. Let O be RequireObjectCoercible(O).
-    // 2. ReturnIfAbrupt(O).
-    if (object.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "");
-        return Value();
-    }
-
-    // 3. If Type(proto) is neither Object nor Null, throw a TypeError exception.
-    if (!proto.isObject() && !proto.isNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "");
-        return Value();
-    }
-
-    // 4. If Type(O) is not Object, return O.
-    if (!object.isObject()) {
-        return object;
-    }
-
-    // 5. Let status be O.[[SetPrototypeOf]](proto).
-    Object* obj = object.toObject(state);
-    bool status = obj->setPrototype(state, proto);
-
-    // 7. If status is false, throw a TypeError exception.
-    if (!status) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "can't set prototype of this object");
-        return Value();
-    }
-
-    return object;
-}
-
-static Value builtinObjectFreeze(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        // If Type(O) is not Object, return O.
-        return argv[0];
-    }
-
-    Object* O = argv[0].asObject();
-
-    // Let status be ? SetIntegrityLevel(O, frozen).
-    // If status is false, throw a TypeError exception.
-    if (!Object::setIntegrityLevel(state, O, false)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().freeze.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-    }
-
-    // Return O.
-    return O;
-}
-
-static Value builtinObjectFromEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (argv[0].isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().fromEntries.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-    Value iterable = argv[0];
-    Object* obj = new Object(state);
-
-    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
-    while (true) {
-        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
-        if (!next.hasValue()) {
-            return obj;
-        }
-
-        Value nextItem = IteratorObject::iteratorValue(state, next.value());
-        if (!nextItem.isObject()) {
-            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
-            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
-        }
-
-        try {
-            // Let k be Get(nextItem, "0").
-            // If k is an abrupt completion, return ? IteratorClose(iter, k).
-            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
-            // Let v be Get(nextItem, "1").
-            // If v is an abrupt completion, return ? IteratorClose(iter, v).
-            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
-
-            ObjectPropertyName key(state, k);
-            obj->defineOwnPropertyThrowsException(state, key,
-                                                  ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-        } catch (const Value& v) {
-            // we should save thrown value bdwgc cannot track thrown value
-            Value exceptionValue = v;
-            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
-            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-        }
-    }
-
-    return obj;
-}
-
-// https://262.ecma-international.org/#sec-object.getownpropertydescriptor
-static Value builtinObjectGetOwnPropertyDescriptor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let obj be ToObject(O).
-    Object* O = argv[0].toObject(state);
-    // Let key be ? ToPropertyKey(P).
-    Value key = argv[1].toPropertyKey(state);
-
-    // Let desc be ? obj.[[GetOwnProperty]](key).
-    // Return FromPropertyDescriptor(desc).
-    return O->getOwnPropertyDescriptor(state, ObjectPropertyName(state, key));
-}
-
-// https://262.ecma-international.org/#sec-object.getownpropertydescriptors
-static Value builtinObjectGetOwnPropertyDescriptors(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Object* obj = argv[0].toObject(state);
-    auto ownKeys = obj->ownPropertyKeys(state);
-    Object* descriptors = new Object(state);
-
-    for (uint64_t i = 0; i < ownKeys.size(); i++) {
-        Value descriptor = obj->getOwnPropertyDescriptor(state, ObjectPropertyName(state, ownKeys[i]));
-        if (!descriptor.isUndefined()) {
-            descriptors->defineOwnProperty(state, ObjectPropertyName(state, ownKeys[i]), ObjectPropertyDescriptor(descriptor, ObjectPropertyDescriptor::AllPresent));
-        }
-    }
-    return descriptors;
-}
-
-enum class GetOwnPropertyKeysType {
-    String,
-    Symbol
-};
-
-static ArrayObject* getOwnPropertyKeys(ExecutionState& state, Value o, GetOwnPropertyKeysType type)
-{
-    // https://www.ecma-international.org/ecma-262/6.0/#sec-getownpropertykeys
-
-    // 1. Let obj be ToObject(O).
-    // 2. ReturnIfAbrupt(obj)
-    auto obj = o.asObject();
-    // 3. Let keys be obj.[[OwnPropertyKeys]]().
-    // 4. ReturnIfAbrupt(keys).
-    auto keys = obj->ownPropertyKeys(state);
-
-    // 5. Let nameList be a new empty List.
-    ValueVectorWithInlineStorage nameList;
-
-    // 6. Repeat for each element nextKey of keys in List order,
-    //  a. If Type(nextKey) is Type, then
-    //      i. Append nextKey as the last element of nameList.
-    bool (Escargot::Value::*func)() const;
-    if (type == GetOwnPropertyKeysType::String) {
-        func = &Value::isString;
-    } else {
-        func = &Value::isSymbol;
-    }
-    for (size_t i = 0; i < keys.size(); ++i) {
-        if ((keys[i].*func)()) {
-            nameList.pushBack(keys[i]);
-        }
-    }
-
-    // 7. Return CreateArrayFromList(nameList).
-    return Object::createArrayFromList(state, nameList.size(), nameList.data());
-}
-
-static Value builtinObjectGetOwnPropertyNames(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertynames
-    Object* O = argv[0].toObject(state);
-    return getOwnPropertyKeys(state, O, GetOwnPropertyKeysType::String);
-}
-
-static Value builtinObjectGetOwnPropertySymbols(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/6.0/#sec-object.getownpropertysymbols
-    Object* O = argv[0].toObject(state);
-    return getOwnPropertyKeys(state, O, GetOwnPropertyKeysType::Symbol);
-}
-
-static Value builtinObjectIsExtensible(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return Value(Value::False);
-    }
-    // Return the Boolean value of the [[Extensible]] internal property of O.
-    return Value(argv[0].asObject()->isExtensible(state));
-}
-
-static Value builtinObjectIsFrozen(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return Value(Value::True);
-    }
-
-    bool result = Object::testIntegrityLevel(state, argv[0].asObject(), false);
-    return Value(result);
-}
-
-static Value builtinObjectIsSealed(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return Value(Value::True);
-    }
-
-    bool result = Object::testIntegrityLevel(state, argv[0].asObject(), true);
-    return Value(result);
-}
-
-static Value builtinObjectSeal(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!argv[0].isObject()) {
-        return argv[0];
-    }
-    Object* O = argv[0].asObject();
-
-    // Let status be ? SetIntegrityLevel(O, sealed).
-    // If status is false, throw a TypeError exception.
-    if (!Object::setIntegrityLevel(state, O, true)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().seal.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-    }
-
-    // Return O.
-    return O;
-}
-
-static Value builtinObjectAssign(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Object.assign ( target, ...sources )
-    // Let to be ? ToObject(target).
-    Object* to = argv[0].toObject(state);
-    // If only one argument was passed, return to.
-    if (argc == 1) {
-        return to;
-    }
-    // Let sources be the List of argument values starting with the second argument.
-    // For each element nextSource of sources, in ascending index order, do
-    for (size_t i = 1; i < argc; i++) {
-        Value nextSource = argv[i];
-        // If nextSource is undefined or null, let keys be a new empty List.
-        Object::OwnPropertyKeyVector keys;
-        Object* from = nullptr;
-        if (!nextSource.isUndefinedOrNull()) {
-            // Let from be ! ToObject(nextSource).
-            from = nextSource.toObject(state);
-            // Let keys be ? from.[[OwnPropertyKeys]]().
-            keys = from->ownPropertyKeys(state);
-        }
-
-        // For each element nextKey of keys in List order, do
-        for (size_t i = 0; i < keys.size(); i++) {
-            Value nextKey = keys[i];
-            // Let desc be ? from.[[GetOwnProperty]](nextKey).
-            auto desc = from->getOwnProperty(state, ObjectPropertyName(state, nextKey));
-            // If desc is not undefined and desc.[[Enumerable]] is true, then
-            if (desc.hasValue() && desc.isEnumerable()) {
-                // Let propValue be ? Get(from, nextKey).
-                Value propValue;
-                if (from->isProxyObject()) {
-                    propValue = from->get(state, ObjectPropertyName(state, Value(nextKey))).value(state, from);
-                } else {
-                    propValue = desc.value(state, from);
-                }
-                // Perform ? Set(to, nextKey, propValue, true).
-                to->setThrowsException(state, ObjectPropertyName(state, nextKey), propValue, to);
-            }
-        }
-    }
-    return to;
-}
-
-static Value builtinObjectIs(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // 19.1.2.10 Object.is ( value1, value2 )
-
-    // Return SameValue(value1, value2).
-    return Value(argv[0].equalsToByTheSameValueAlgorithm(state, argv[1]));
-}
-
-static Value builtinObjectKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // 19.1.2.16 Object.keys ( O )
-
-    // Let obj be ? ToObject(O).
-    Object* obj = argv[0].toObject(state);
-    // Let nameList be ? EnumerableOwnProperties(obj, "key").
-    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::Key);
-    // Return CreateArrayFromList(nameList).
-    return Object::createArrayFromList(state, nameList.size(), nameList.data());
-}
-
-static Value builtinObjectValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // 19.1.2.21 Object.values ( O )
-
-    // Let obj be ? ToObject(O).
-    Object* obj = argv[0].toObject(state);
-    // Let nameList be ? EnumerableOwnProperties(obj, "value").
-    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::Value);
-    // Return CreateArrayFromList(nameList).
-    return Object::createArrayFromList(state, nameList.size(), nameList.data());
-}
-
-static Value builtinObjectEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // 19.1.2.5 Object.entries ( O )
-
-    // Let obj be ? ToObject(O).
-    Object* obj = argv[0].toObject(state);
-    // Let nameList be ? EnumerableOwnProperties(obj, "key+value").
-    auto nameList = Object::enumerableOwnProperties(state, obj, EnumerableOwnPropertiesType::KeyAndValue);
-    // Return CreateArrayFromList(nameList).
-    return Object::createArrayFromList(state, nameList.size(), nameList.data());
-}
-
-void GlobalObject::installObject(ExecutionState& state)
-{
-    const StaticStrings& strings = state.context()->staticStrings();
-
-    m_object = new NativeFunctionObject(state, NativeFunctionInfo(strings.Object, builtinObjectConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_object->setGlobalIntrinsicObject(state);
-    m_object->setFunctionPrototype(state, m_objectPrototype);
-
-    // $19.1.2.2 Object.create (O [,Properties])
-    m_objectCreate = new NativeFunctionObject(state, NativeFunctionInfo(strings.create, builtinObjectCreate, 2, NativeFunctionInfo::Strict));
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.create),
-                                ObjectPropertyDescriptor(m_objectCreate,
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    // 19.1.2.3 Object.defineProperties ( O, Properties )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.defineProperties),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.defineProperties, builtinObjectDefineProperties, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.4 Object.defineProperty ( O, P, Attributes )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.defineProperty),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.defineProperty, builtinObjectDefineProperty, 3, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.5 Object.freeze ( O )
-    m_objectFreeze = new NativeFunctionObject(state, NativeFunctionInfo(strings.freeze, builtinObjectFreeze, 1, NativeFunctionInfo::Strict));
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.freeze),
-                                ObjectPropertyDescriptor(m_objectFreeze,
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // 19.1.2.7 Object.fromEntries ( iterable )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.fromEntries),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.fromEntries, builtinObjectFromEntries, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyDescriptor),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyDescriptor, builtinObjectGetOwnPropertyDescriptor, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.7 Object.getOwnPropertyNames ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyNames),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyNames, builtinObjectGetOwnPropertyNames, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertySymbols),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertySymbols, builtinObjectGetOwnPropertySymbols, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getOwnPropertyDescriptors),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getOwnPropertyDescriptors, builtinObjectGetOwnPropertyDescriptors, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.9 Object.getPrototypeOf ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.getPrototypeOf),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.getPrototypeOf, builtinObjectGetPrototypeOf, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.11 Object.isExtensible ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isExtensible),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isExtensible, builtinObjectIsExtensible, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.12 Object.isFrozen ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isFrozen),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isFrozen, builtinObjectIsFrozen, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.13 Object.isSealed ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.isSealed),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isSealed, builtinObjectIsSealed, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.14 Object.keys ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.keys),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.keys, builtinObjectKeys, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.15 Object.preventExtensions ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.preventExtensions),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.preventExtensions, builtinObjectPreventExtensions, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.17 Object.seal ( O )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.seal),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.seal, builtinObjectSeal, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 19.1.2.20 Object.setPrototypeOf ( O, proto )
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.setPrototypeOf),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.setPrototypeOf, builtinObjectSetPrototypeOf, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    // ES6+ Object.assign
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.assign),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.assign, builtinObjectAssign, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // ES6+ Object.is
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.is),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.is, builtinObjectIs, 2, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.constructor),
-                                         ObjectPropertyDescriptor(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.toString),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.toString, builtinObjectToString, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.valueOf),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.valueOf, builtinObjectValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // ES2017 Object.values
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.values),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.values, builtinObjectValues, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // ES2017 Object.entries
-    m_object->defineOwnProperty(state, ObjectPropertyName(strings.entries),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.entries, builtinObjectEntries, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.1.3.2 Object.prototype.hasOwnProperty(V)
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.hasOwnProperty),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.hasOwnProperty, builtinObjectHasOwnProperty, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.1.3.4 Object.prototype.isPrototypeOf(V)
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.isPrototypeOf),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.isPrototypeOf, builtinObjectIsPrototypeOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.1.3.4 Object.prototype.propertyIsEnumerable(V)
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.propertyIsEnumerable),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.propertyIsEnumerable, builtinObjectPropertyIsEnumerable, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.1.3.5 Object.prototype.toLocaleString()
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.toLocaleString),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.toLocaleString, builtinObjectToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $19.1.3.4 Object.prototype.propertyIsEnumerable(V)
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().propertyIsEnumerable),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().propertyIsEnumerable, builtinObjectPropertyIsEnumerable, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    JSGetterSetter gs(
-        new NativeFunctionObject(state, NativeFunctionInfo(strings.get__proto__, builtinObject__proto__Getter, 0, NativeFunctionInfo::Strict)),
-        new NativeFunctionObject(state, NativeFunctionInfo(strings.set__proto__, builtinObject__proto__Setter, 1, NativeFunctionInfo::Strict)));
-    ObjectPropertyDescriptor __proto__desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-    m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__proto__), __proto__desc);
-    defineOwnProperty(state, ObjectPropertyName(strings.Object),
-                      ObjectPropertyDescriptor(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_objectPrototypeToString = new NativeFunctionObject(state, NativeFunctionInfo(strings.toString, builtinObjectToString, 0, NativeFunctionInfo::Strict));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinPromise.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinPromise.cpp
deleted file mode 100644 (file)
index 4949c79..0000000
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (c) 2017-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/VMInstance.h"
-#include "runtime/PromiseObject.h"
-#include "runtime/ArrayObject.h"
-#include "runtime/JobQueue.h"
-#include "runtime/SandBox.h"
-#include "runtime/NativeFunctionObject.h"
-#include "runtime/IteratorObject.h"
-#include "runtime/ExtendedNativeFunctionObject.h"
-
-namespace Escargot {
-
-// $25.4.3 Promise(executor)
-static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise constructor should be called with new Promise()");
-    }
-
-    Value executor = argv[0];
-    if (!executor.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise executor is not a function object");
-    }
-
-    // Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->promisePrototype();
-    });
-    PromiseObject* promise = new PromiseObject(state, proto);
-
-    PromiseReaction::Capability capability = promise->createResolvingFunctions(state);
-
-    // PromiseHook for Promise initialization case
-    if (UNLIKELY(state.context()->vmInstance()->isPromiseHookRegistered())) {
-        // Note) To pass parent promise, we allocate the second argument (argv[1]) for the parent promise
-        // otherwise, the second argument would be ignored
-        state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Init, promise, (argc > 1) ? argv[1] : Value());
-    }
-
-    SandBox sb(state.context());
-    auto res = sb.run([&]() -> Value {
-        Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction };
-        Object::call(state, executor, Value(), 2, arguments);
-        return Value();
-    });
-    if (!res.error.isEmpty()) {
-        Value arguments[] = { res.error };
-        Object::call(state, capability.m_rejectFunction, Value(), 1, arguments);
-    }
-
-    return promise;
-}
-
-// https://tc39.es/ecma262/#sec-getpromiseresolve
-static Value getPromiseResolve(ExecutionState& state, Object* promiseConstructor)
-{
-    // Assert: IsConstructor(promiseConstructor) is true.
-    // Let promiseResolve be ? Get(promiseConstructor, "resolve").
-    auto promiseResolve = promiseConstructor->get(state, state.context()->staticStrings().resolve).value(state, promiseConstructor);
-    // If IsCallable(promiseResolve) is false, throw a TypeError exception.
-    if (!promiseResolve.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Promise resolve is not callable");
-    }
-    // Return promiseResolve.
-    return promiseResolve;
-}
-
-static Value builtinPromiseAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://tc39.es/ecma262/#sec-performpromiseall
-    auto strings = &state.context()->staticStrings();
-
-    // Let C be the this value.
-    // If Type(C) is not Object, throw a TypeError exception.
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->all.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    Object* C = thisValue.asObject();
-    // Let promiseCapability be NewPromiseCapability(C).
-    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
-    // Let promiseResolve be GetPromiseResolve(C).
-    Value promiseResolve;
-    try {
-        promiseResolve = getPromiseResolve(state, C);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let iteratorRecord be GetIterator(iterable).
-    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
-    IteratorRecord* iteratorRecord;
-    try {
-        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
-    Value result;
-    try {
-        // Let values be a new empty List.
-        ValueVector* values = new ValueVector();
-        // Let remainingElementsCount be a new Record { [[value]]: 1 }.
-        size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
-
-        // Let index be 0.
-        int64_t index = 0;
-
-        // Repeat
-        while (true) {
-            // Let next be IteratorStep(iteratorRecord).
-            Optional<Object*> next;
-            try {
-                next = IteratorObject::iteratorStep(state, iteratorRecord);
-            } catch (const Value& e) {
-                // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
-                iteratorRecord->m_done = true;
-                // ReturnIfAbrupt(next).
-                state.throwException(e);
-            }
-            // If next is false,
-            if (!next.hasValue()) {
-                // set iteratorRecord.[[done]] to true.
-                iteratorRecord->m_done = true;
-                // Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] − 1.
-                *remainingElementsCount = *remainingElementsCount - 1;
-                // If remainingElementsCount.[[value]] is 0,
-                if (*remainingElementsCount == 0) {
-                    // Let valuesArray be CreateArrayFromList(values).
-                    // Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
-                    Value argv = Object::createArrayFromList(state, *values);
-                    Value resolveResult = Object::call(state, promiseCapability.m_resolveFunction, Value(), 1, &argv);
-                }
-                // Return resultCapability.[[Promise]].
-                result = promiseCapability.m_promise;
-                break;
-            }
-            // Let nextValue be IteratorValue(next).
-            Value nextValue;
-            try {
-                nextValue = IteratorObject::iteratorValue(state, next.value());
-            } catch (const Value& e) {
-                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
-                iteratorRecord->m_done = true;
-                // ReturnIfAbrupt(nextValue).
-                state.throwException(e);
-            }
-            // Append undefined to values.
-            values->pushBack(Value());
-            // Let nextPromise be Invoke(constructor, "resolve", « nextValue »).
-            Value nextPromise = Object::call(state, promiseResolve, C, 1, &nextValue);
-
-            // Let resolveElement be a new built-in function object as defined in Promise.all Resolve Element Functions.
-            ExtendedNativeFunctionObject* resolveElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllResolveElementFunction, 1, NativeFunctionInfo::Strict));
-
-            // Set the [[AlreadyCalled]] internal slot of resolveElement to a new Record {[[value]]: false }.
-            // Set the [[Index]] internal slot of resolveElement to index.
-            // Set the [[Values]] internal slot of resolveElement to values.
-            // Set the [[Capabilities]] internal slot of resolveElement to resultCapability.
-            // Set the [[RemainingElements]] internal slot of resolveElement to remainingElementsCount.
-            bool* alreadyCalled = new (PointerFreeGC) bool(false);
-
-            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
-            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
-            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
-            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, promiseCapability.m_resolveFunction);
-            resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, promiseCapability.m_rejectFunction);
-            resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
-
-            // Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] + 1.
-            *remainingElementsCount = *remainingElementsCount + 1;
-            // Perform ? Invoke(nextPromise, "then", « resolveElement, resultCapability.[[Reject]] »).
-            Object* nextPromiseObject = nextPromise.toObject(state);
-            Value argv[] = { Value(resolveElement), Value(promiseCapability.m_rejectFunction) };
-            Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv);
-            // Increase index by 1.
-            index++;
-        }
-    } catch (const Value& v) {
-        Value exceptionValue = v;
-        // If result is an abrupt completion,
-        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
-        // IfAbruptRejectPromise(result, promiseCapability).
-        try {
-            if (!iteratorRecord->m_done) {
-                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-            }
-        } catch (const Value& v) {
-            exceptionValue = v;
-        }
-
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Return Completion(result).
-    return result;
-}
-
-static Value builtinPromiseRace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://tc39.es/ecma262/#sec-performpromiserace
-    auto strings = &state.context()->staticStrings();
-    // Let C be the this value.
-    // If Type(C) is not Object, throw a TypeError exception.
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->race.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    Object* C = thisValue.asObject();
-
-    // Let promiseCapability be NewPromiseCapability(C).
-    // ReturnIfAbrupt(promiseCapability).
-    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
-    // Let promiseResolve be GetPromiseResolve(C).
-    Value promiseResolve;
-    try {
-        promiseResolve = getPromiseResolve(state, C);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let iteratorRecord be GetIterator(iterable).
-    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
-    IteratorRecord* iteratorRecord;
-    try {
-        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Let rejectResult be Call(capability.[[Reject]], undefined, «value.[[value]]»).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
-    Value result;
-    try {
-        // Repeat
-        while (true) {
-            // Let next be IteratorStep(iteratorRecord).
-            Optional<Object*> next;
-            try {
-                next = IteratorObject::iteratorStep(state, iteratorRecord);
-            } catch (const Value& e) {
-                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
-                // ReturnIfAbrupt(next).
-                iteratorRecord->m_done = true;
-                state.throwException(e);
-            }
-            // If next is false, then
-            if (!next.hasValue()) {
-                // Set iteratorRecord.[[done]] to true.
-                iteratorRecord->m_done = true;
-                // Return resultCapability.[[Promise]].
-                result = promiseCapability.m_promise;
-                break;
-            }
-
-            // Let nextValue be IteratorValue(next).
-            Value nextValue;
-            try {
-                nextValue = IteratorObject::iteratorValue(state, next.value());
-            } catch (const Value& e) {
-                // If next is an abrupt completion, set iteratorRecord.[[done]] to true.
-                iteratorRecord->m_done = true;
-                // ReturnIfAbrupt(next).
-                state.throwException(e);
-            }
-
-            // Let nextPromise be Invoke(C, "resolve", «nextValue»).
-            Value nextPromise = Object::call(state, promiseResolve, C, 1, &nextValue);
-            // Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).
-            Object* nextPromiseObject = nextPromise.toObject(state);
-            Value argv[] = { Value(promiseCapability.m_resolveFunction), Value(promiseCapability.m_rejectFunction) };
-            Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv);
-        }
-    } catch (const Value& e) {
-        Value exceptionValue = e;
-        // If result is an abrupt completion, then
-        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
-        // IfAbruptRejectPromise(result, promiseCapability).
-        try {
-            if (!iteratorRecord->m_done) {
-                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-            }
-        } catch (const Value& v) {
-            exceptionValue = v;
-        }
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Return Completion(result).
-    return result;
-}
-
-static Value builtinPromiseReject(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Object* thisObject = thisValue.toObject(state);
-    PromiseReaction::Capability capability = PromiseObject::newPromiseCapability(state, thisObject);
-
-    Value arguments[] = { argv[0] };
-    Object::call(state, capability.m_rejectFunction, Value(), 1, arguments);
-    return capability.m_promise;
-}
-
-// http://www.ecma-international.org/ecma-262/10.0/#sec-promise.resolve
-static Value builtinPromiseResolve(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let C be the this value.
-    const Value& C = thisValue;
-    // If Type(C) is not Object, throw a TypeError exception.
-    if (!C.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Promise.string(), false, state.context()->staticStrings().resolve.string(), "%s: PromiseResolve called on non-object");
-    }
-    // Return ? PromiseResolve(C, x).
-    return PromiseObject::promiseResolve(state, C.asObject(), argv[0]);
-}
-
-static Value builtinPromiseCatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Object* thisObject = thisValue.toObject(state);
-    Value onRejected = argv[0];
-    Value then = thisObject->get(state, strings->then).value(state, thisObject);
-    Value arguments[] = { Value(), onRejected };
-    return Object::call(state, then, thisObject, 2, arguments);
-}
-
-
-static Value builtinPromiseFinally(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-promise.prototype.finally
-    auto strings = &state.context()->staticStrings();
-
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->finally.string(), "%s: not a Promise object");
-    }
-
-    Object* thisObject = thisValue.asObject();
-    Value C = thisObject->speciesConstructor(state, state.context()->globalObject()->promise());
-
-    Value onFinally = argv[0];
-    Value arguments[] = { onFinally, onFinally };
-
-    if (onFinally.isCallable()) {
-        ExtendedNativeFunctionObject* thenFinally = new ExtendedNativeFunctionObjectImpl<2>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseThenFinally, 1, NativeFunctionInfo::Strict));
-        thenFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Constructor, C);
-        thenFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::OnFinally, onFinally);
-
-        ExtendedNativeFunctionObject* catchFinally = new ExtendedNativeFunctionObjectImpl<2>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseCatchFinally, 1, NativeFunctionInfo::Strict));
-        catchFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Constructor, C);
-        catchFinally->setInternalSlot(PromiseObject::BuiltinFunctionSlot::OnFinally, onFinally);
-
-        arguments[0] = thenFinally;
-        arguments[1] = catchFinally;
-    }
-
-    Value then = thisObject->get(state, strings->then).value(state, thisObject);
-    return Object::call(state, then, thisObject, 2, arguments);
-}
-
-static Value builtinPromiseThen(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    if (!thisValue.isObject() || !thisValue.asObject()->isPromiseObject())
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->then.string(), "%s: not a Promise object");
-    Value C = thisValue.asObject()->speciesConstructor(state, state.context()->globalObject()->promise());
-    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C.asObject(), thisValue.asObject()->asPromiseObject());
-    return thisValue.asObject()->asPromiseObject()->then(state, argv[0], argv[1], promiseCapability).value();
-}
-
-// https://tc39.es/ecma262/#sec-performpromiseallsettled
-static Value performPromiseAllSettled(ExecutionState& state, IteratorRecord* iteratorRecord, Object* constructor, PromiseReaction::Capability& resultCapability, Value promiseResolve)
-{
-    // Assert: ! IsConstructor(constructor) is true.
-    // Assert: resultCapability is a PromiseCapability Record.
-    // Let values be a new empty List.
-    ValueVector* values = new ValueVector();
-    // Let remainingElementsCount be a new Record { [[Value]]: 1 }.
-    size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
-    // Let index be 0.
-    size_t index = 0;
-
-    // Repeat,
-    while (true) {
-        // Let next be IteratorStep(iteratorRecord).
-        Optional<Object*> next;
-        try {
-            next = IteratorObject::iteratorStep(state, iteratorRecord);
-        } catch (const Value& e) {
-            // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
-            iteratorRecord->m_done = true;
-            // ReturnIfAbrupt(next).
-            state.throwException(e);
-        }
-
-        // If next is false, then
-        if (!next.hasValue()) {
-            // Set iteratorRecord.[[Done]] to true.
-            iteratorRecord->m_done = true;
-            // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
-            *remainingElementsCount = *remainingElementsCount - 1;
-            // If remainingElementsCount.[[Value]] is 0, then
-            if (*remainingElementsCount == 0) {
-                // Let valuesArray be ! CreateArrayFromList(values).
-                Value valuesArray = ArrayObject::createArrayFromList(state, *values);
-                // Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
-                Object::call(state, resultCapability.m_resolveFunction, Value(), 1, &valuesArray);
-            }
-            // Return resultCapability.[[Promise]].
-            return resultCapability.m_promise;
-        }
-
-        // Let nextValue be IteratorValue(next).
-        Value nextValue;
-        try {
-            nextValue = IteratorObject::iteratorValue(state, next.value());
-        } catch (const Value& e) {
-            // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
-            iteratorRecord->m_done = true;
-            // ReturnIfAbrupt(nextValue).
-            state.throwException(e);
-        }
-
-        // Append undefined to values.
-        values->pushBack(Value());
-        // Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
-        Value nextValueArgv = nextValue;
-        Value nextPromise = Object::call(state, promiseResolve, constructor, 1, &nextValueArgv);
-        // Let steps be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
-        // Let resolveElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
-        // Let alreadyCalled be the Record { [[Value]]: false }.
-        bool* alreadyCalled = new (PointerFreeGC) bool(false);
-        // Set resolveElement.[[AlreadyCalled]] to alreadyCalled.
-        // Set resolveElement.[[Index]] to index.
-        // Set resolveElement.[[Values]] to values.
-        // Set resolveElement.[[Capability]] to resultCapability.
-        // Set resolveElement.[[RemainingElements]] to remainingElementsCount.
-        auto resolveElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllSettledResolveElementFunction, 1, NativeFunctionInfo::Strict));
-        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
-        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
-        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
-        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
-        resolveElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
-        resolveElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
-
-        // Let rejectSteps be the algorithm steps defined in Promise.allSettled Reject Element Functions.
-        // Let rejectElement be ! CreateBuiltinFunction(rejectSteps, « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
-        // Set rejectElement.[[AlreadyCalled]] to alreadyCalled.
-        // Set rejectElement.[[Index]] to index.
-        // Set rejectElement.[[Values]] to values.
-        // Set rejectElement.[[Capability]] to resultCapability.
-        // Set rejectElement.[[RemainingElements]] to remainingElementsCount.
-        auto rejectElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAllSettledRejectElementFunction, 1, NativeFunctionInfo::Strict));
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Values, values);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
-
-        // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
-        *remainingElementsCount = *remainingElementsCount + 1;
-        // Perform ? Invoke(nextPromise, "then", « resolveElement, rejectElement »).
-        Value argv[2] = { resolveElement, rejectElement };
-        Object::call(state, Object::getMethod(state, nextPromise, state.context()->staticStrings().then), nextPromise, 2, argv);
-        // Set index to index + 1.
-        index++;
-    }
-
-    return Value();
-}
-
-// https://tc39.es/ecma262/#sec-promise.allsettled
-static Value builtinPromiseAllSettled(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let C be the this value.
-    // If Type(C) is not Object, throw a TypeError exception.
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "this value of allSettled is not Object");
-    }
-    Object* C = thisValue.asObject();
-    // Let promiseCapability be ? NewPromiseCapability(C).
-    auto promiseCapability = PromiseObject::newPromiseCapability(state, C);
-    // Let promiseResolve be GetPromiseResolve(C).
-    Value promiseResolve;
-    try {
-        promiseResolve = getPromiseResolve(state, C);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let iteratorRecord be GetIterator(iterable).
-    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
-    IteratorRecord* iteratorRecord;
-    try {
-        iteratorRecord = IteratorObject::getIterator(state, argv[0]);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    Value result;
-    // Let result be PerformPromiseAllSettled(iteratorRecord, C, promiseCapability).
-    try {
-        result = performPromiseAllSettled(state, iteratorRecord, C, promiseCapability, promiseResolve);
-    } catch (const Value& v) {
-        Value exceptionValue = v;
-        // If result is an abrupt completion,
-        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
-        if (!iteratorRecord->m_done) {
-            try {
-                result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-            } catch (const Value& v) {
-                // IfAbruptRejectPromise(result, promiseCapability).
-                // If value is an abrupt completion,
-                // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-                Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
-                // Return capability.[[Promise]].
-                return promiseCapability.m_promise;
-            }
-        } else {
-            // IfAbruptRejectPromise(result, promiseCapability).
-            // If value is an abrupt completion,
-            // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-            Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &exceptionValue);
-            // Return capability.[[Promise]].
-            return promiseCapability.m_promise;
-        }
-    }
-    // Return Completion(result).
-    return result;
-}
-
-// https://tc39.es/ecma262/#sec-performpromiseany
-static Value performPromiseAny(ExecutionState& state, IteratorRecord* iteratorRecord, Object* constructor, const PromiseReaction::Capability& resultCapability, const Value& promiseResolve)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    // Assert: ! IsConstructor(constructor) is true.
-    // Assert: ! IsCallable(promiseResolve) is true.
-    // Let errors be a new empty List.
-    ValueVector* errors = new ValueVector();
-    // Let remainingElementsCount be the Record { [[Value]]: 1 }.
-    size_t* remainingElementsCount = new (PointerFreeGC) size_t(1);
-    // Let index be 0.
-    int64_t index = 0;
-    // Repeat,
-    while (true) {
-        // Let next be IteratorStep(iteratorRecord).
-        // If next is an abrupt completion, set iteratorRecord.[[Done]] to true.
-        // ReturnIfAbrupt(next).
-        Optional<Object*> next;
-        try {
-            next = IteratorObject::iteratorStep(state, iteratorRecord);
-        } catch (const Value& v) {
-            iteratorRecord->m_done = true;
-            throw v;
-        }
-
-        // If next is false, then
-        if (!next.hasValue()) {
-            // Set iteratorRecord.[[Done]] to true.
-            iteratorRecord->m_done = true;
-            // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
-            *remainingElementsCount = *remainingElementsCount - 1;
-            // If remainingElementsCount.[[Value]] is 0, then
-            if (*remainingElementsCount == 0) {
-                // Let error be a newly created AggregateError object.
-                ErrorObject* error = ErrorObject::createBuiltinError(state, ErrorObject::AggregateError, "Got AggregateError on processing Promise.any");
-                // Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
-                error->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, String::fromASCII("errors")),
-                                                        ObjectPropertyDescriptor(Object::createArrayFromList(state, *errors),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
-                // Return ThrowCompletion(error).
-                throw Value(error);
-            }
-            // Return resultCapability.[[Promise]].
-            return resultCapability.m_promise;
-        }
-
-        // Let nextValue be IteratorValue(next).
-        Value nextValue;
-        try {
-            nextValue = IteratorObject::iteratorValue(state, next.value());
-        } catch (const Value& v) {
-            // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
-            iteratorRecord->m_done = true;
-            // ReturnIfAbrupt(nextValue).
-            throw v;
-        }
-        // Append undefined to errors.
-        errors->pushBack(Value());
-        // Let nextPromise be ? Call(promiseResolve, constructor, « nextValue »).
-        Value argv = nextValue;
-        Value nextPromise = Object::call(state, promiseResolve, constructor, 1, &argv);
-        // Let steps be the algorithm steps defined in Promise.any Reject Element Functions.
-        // Let rejectElement be ! CreateBuiltinFunction(steps, « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
-        ExtendedNativeFunctionObject* rejectElement = new ExtendedNativeFunctionObjectImpl<6>(state, NativeFunctionInfo(AtomicString(), PromiseObject::promiseAnyRejectElementFunction, 1, NativeFunctionInfo::Strict));
-        // Set rejectElement.[[AlreadyCalled]] to false.
-        // Set rejectElement.[[Index]] to index.
-        // Set rejectElement.[[Errors]] to errors.
-        // Set rejectElement.[[Capability]] to resultCapability.
-        // Set rejectElement.[[RemainingElements]] to remainingElementsCount.
-        bool* alreadyCalled = new (PointerFreeGC) bool(false);
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::AlreadyCalled, alreadyCalled);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Index, Value(index));
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::Errors, errors);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Resolve, resultCapability.m_resolveFunction);
-        rejectElement->setInternalSlot(PromiseObject::BuiltinFunctionSlot::Reject, resultCapability.m_rejectFunction);
-        rejectElement->setInternalSlotAsPointer(PromiseObject::BuiltinFunctionSlot::RemainingElements, remainingElementsCount);
-        // Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
-        *remainingElementsCount = *remainingElementsCount + 1;
-
-        // Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], rejectElement »).
-        Object* nextPromiseObject = nextPromise.toObject(state);
-        Value argv2[] = { Value(resultCapability.m_resolveFunction), Value(rejectElement) };
-        Object::call(state, nextPromiseObject->get(state, strings->then).value(state, nextPromiseObject), nextPromiseObject, 2, argv2);
-        // Set index to index + 1.
-        index++;
-    }
-    ASSERT_NOT_REACHED();
-}
-
-// https://tc39.es/ecma262/#sec-promise.any
-static Value builtinPromiseAny(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    // Let C be the this value.
-    // If Type(C) is not Object, throw a TypeError exception.
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Promise.string(), false, strings->all.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    Object* C = thisValue.asObject();
-
-    // Let promiseCapability be NewPromiseCapability(C).
-    PromiseReaction::Capability promiseCapability = PromiseObject::newPromiseCapability(state, C);
-    // Let promiseResolve be GetPromiseResolve(C).
-    // IfAbruptRejectPromise(promiseResolve, promiseCapability).
-    Value promiseResolve;
-    try {
-        promiseResolve = getPromiseResolve(state, C);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let iteratorRecord be GetIterator(iterable).
-    // IfAbruptRejectPromise(iteratorRecord, promiseCapability).
-    const Value& iterable = argv[0];
-    IteratorRecord* iteratorRecord = nullptr;
-    try {
-        iteratorRecord = IteratorObject::getIterator(state, iterable);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If value is an abrupt completion,
-        // Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        // Return capability.[[Promise]].
-        return promiseCapability.m_promise;
-    }
-
-    // Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve).
-    Value result;
-    try {
-        result = performPromiseAny(state, iteratorRecord, C, promiseCapability, promiseResolve);
-    } catch (const Value& v) {
-        Value thrownValue = v;
-        // If result is an abrupt completion, then
-        // If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
-        try {
-            if (!iteratorRecord->m_done) {
-                IteratorObject::iteratorClose(state, iteratorRecord, thrownValue, true);
-            }
-        } catch (const Value& v) {
-            thrownValue = v;
-        }
-        // IfAbruptRejectPromise(result, promiseCapability).
-        Object::call(state, promiseCapability.m_rejectFunction, Value(), 1, &thrownValue);
-        return promiseCapability.m_promise;
-    }
-    // Return Completion(result).
-    return result;
-}
-
-void GlobalObject::installPromise(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_promise = new NativeFunctionObject(state, NativeFunctionInfo(strings->Promise, builtinPromiseConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_promise->setGlobalIntrinsicObject(state);
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_promise->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    m_promisePrototype = new Object(state);
-    m_promisePrototype->setGlobalIntrinsicObject(state, true);
-
-    m_promisePrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().Promise.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $25.4.4.1 Promise.all(iterable);
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->all),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->all, builtinPromiseAll, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.4.3 Promise.race(iterable)
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->race),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->race, builtinPromiseRace, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.4.4 Promise.reject(r)
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reject),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reject, builtinPromiseReject, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.4.5 Promise.resolve(r)
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->resolve),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->resolve, builtinPromiseResolve, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.5.1 Promise.prototype.catch(onRejected)
-    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->stringCatch),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->stringCatch, builtinPromiseCatch, 1, NativeFunctionInfo::Strict)),
-                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
-    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->then),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->then, builtinPromiseThen, 2, NativeFunctionInfo::Strict)),
-                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.6.5.3 Promise.prototype.finally ( onFinally )
-    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->finally),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->finally, builtinPromiseFinally, 1, NativeFunctionInfo::Strict)),
-                                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $25.4.5.4 Promise.prototype [ @@toStringTag ]
-    m_promisePrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().Promise.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_promise->setFunctionPrototype(state, m_promisePrototype);
-
-    // Promise.allSettled ( iterable )
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->allSettled),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->allSettled, builtinPromiseAllSettled, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // Promise.any ( iterable )
-    m_promise->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->any),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->any, builtinPromiseAny, 1, NativeFunctionInfo::Strict)),
-                                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    defineOwnProperty(state, ObjectPropertyName(strings->Promise),
-                      ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinProxy.cpp
deleted file mode 100644 (file)
index 5d10aee..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "ProxyObject.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/ArrayObject.h"
-#include "runtime/NativeFunctionObject.h"
-#include "runtime/ExtendedNativeFunctionObject.h"
-
-namespace Escargot {
-
-// $26.2.1 The Proxy Constructor
-static Value builtinProxyConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Proxy.string(), false, String::emptyString, "%s: calling a builtin Proxy constructor without new is forbidden");
-        return Value();
-    }
-
-    Value target = argv[0];
-    Value handler = argv[1];
-
-    return ProxyObject::createProxy(state, target, handler);
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-proxy-revocation-functions
-static Value builtinProxyRevoke(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-
-    ExtendedNativeFunctionObject* revoke = state.resolveCallee()->asExtendedNativeFunctionObject();
-    ASSERT(revoke);
-
-    // 1. Let p be the value of F’s [[RevocableProxy]] internal slot.
-    Value p = revoke->internalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy);
-
-    // 2. If p is null, return undefined.
-    if (p.isNull()) {
-        return Value();
-    }
-
-    ProxyObject* proxy = p.asObject()->asProxyObject();
-
-    // 3. Set the value of F’s [[RevocableProxy]] internal slot to null.
-    revoke->setInternalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy, Value(Value::Null));
-
-    // 5. Set the [[ProxyTarget]] internal slot of p to null.
-    proxy->setTarget(nullptr);
-
-    // 6. Set the [[ProxyHandler]] internal slot of p to null.
-    proxy->setHandler(nullptr);
-
-    // 6. Return undefined.
-    return Value();
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-proxy.revocable
-static Value builtinProxyRevocable(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-
-    Value target = argv[0];
-    Value handler = argv[1];
-
-    // 1. Let p be ProxyCreate(target, handler).
-    Value proxy = ProxyObject::createProxy(state, target, handler);
-
-    // 3. Let revoker be a new built-in function object as defined in 26.2.2.1.1.
-    // 4. Set the [[RevocableProxy]] internal slot of revoker to p.
-    ExtendedNativeFunctionObject* revoker = new ExtendedNativeFunctionObjectImpl<1>(state, NativeFunctionInfo(AtomicString(), builtinProxyRevoke, 0, NativeFunctionInfo::Strict));
-    revoker->setInternalSlot(ProxyObject::BuiltinFunctionSlot::RevocableProxy, proxy);
-
-    // 5. Let result be ObjectCreate(%ObjectPrototype%).
-    Object* result = new Object(state);
-
-    // 6. Perform CreateDataProperty(result, "proxy", p).
-    result->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->proxy),
-                                             ObjectPropertyDescriptor(proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 7. Perform CreateDataProperty(result, "revoke", revoker).
-    result->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->revoke),
-                                             ObjectPropertyDescriptor(revoker, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // 8. Return result.
-    return result;
-}
-
-void GlobalObject::installProxy(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_proxy = new NativeFunctionObject(state, NativeFunctionInfo(strings->Proxy, builtinProxyConstructor, 2), NativeFunctionObject::__ForBuiltinProxyConstructor__);
-    m_proxy->setGlobalIntrinsicObject(state);
-
-    m_proxy->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->revocable), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->revocable, builtinProxyRevocable, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(strings->Proxy),
-                      ObjectPropertyDescriptor(m_proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinReflect.cpp
deleted file mode 100644 (file)
index 67d6328..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/Object.h"
-#include "runtime/ProxyObject.h"
-#include "runtime/NativeFunctionObject.h"
-#include "interpreter/ByteCodeInterpreter.h"
-#include "ArrayObject.h"
-#include "VMInstance.h"
-
-namespace Escargot {
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.apply
-static Value builtinReflectApply(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-    Value thisArgument = argv[1];
-    Value argList = argv[2];
-
-    // 1. If IsCallable(target) is false, throw a TypeError exception.
-    if (!target.isObject() || !target.asObject()->isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: calling a not-callable target in apply function is forbidden");
-    }
-
-    // 2. Let args be CreateListFromArrayLike(argumentsList).
-    auto args = Object::createListFromArrayLike(state, argList);
-
-    // 5. Return Call(target, thisArgument, args).
-    return Object::call(state, target, thisArgument, args.size(), args.data());
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.construct
-static Value builtinReflectConstruct(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-    Value argList = argv[1];
-    Value newTargetArg = argc > 2 ? argv[2] : target;
-
-    // 1. If IsConstructor(target) is false, throw a TypeError exception.
-    if (!target.isConstructor()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.construct should has a construct method");
-    }
-
-    // 2. If newTarget is not present, let newTarget be target.
-    // 3. Else, if IsConstructor(newTarget) is false, throw a TypeError exception.
-    if (!newTargetArg.isConstructor()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The new target of Reflect.construct should be a constructor");
-    }
-
-    // 4. Let args be CreateListFromArrayLike(argumentsList).
-    auto args = Object::createListFromArrayLike(state, argList);
-    // 6. Return Construct(target, args, newTarget).
-    return Object::construct(state, target, args.size(), args.data(), newTargetArg.asObject());
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.defineproperty
-static Value builtinReflectDefineProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.defineProperty should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 3. Let desc be ToPropertyDescriptor(attributes).
-    ObjectPropertyDescriptor desc(state, argv[2].asObject());
-
-    // 6. Return target.[[DefineOwnProperty]](key, desc).
-    return Value(target.asObject()->defineOwnProperty(state, ObjectPropertyName(state, key), desc));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.deleteproperty
-static Value builtinReflectDeleteProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.deleteProperty should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 4. Return target.[[Delete]](key).
-    return Value(target.asObject()->deleteOwnProperty(state, ObjectPropertyName(state, key)));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.get
-static Value builtinReflectGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.get should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 4. If receiver is not present, then
-    // 4.a. Let receiver be target.
-    Value receiver = argc > 2 ? argv[2] : target;
-
-    // 5. Return target.[[Get]](key, receiver).
-    return target.asObject()->get(state, ObjectPropertyName(state, key)).value(state, receiver);
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.getownpropertydescriptor
-static Value builtinReflectGetOwnPropertyDescriptor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.getOwnPropertyDescriptor should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 4. Let desc be target.[[GetOwnProperty]](key).
-    ObjectGetResult desc = target.asObject()->getOwnProperty(state, ObjectPropertyName(state, key));
-
-    // 6. Return FromPropertyDescriptor(desc).
-    return desc.fromPropertyDescriptor(state, target.asObject());
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.getprototypeof
-static Value builtinReflectGetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.getPrototypeOf should be an Object");
-    }
-
-    // 2. Return target.[[GetPrototypeOf]]().
-    return target.asObject()->getPrototype(state);
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.has
-static Value builtinReflectHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.has should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 4. Return target.[[HasProperty]](key).
-    return Value(target.asObject()->hasProperty(state, ObjectPropertyName(state, key)));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.isextensible
-static Value builtinReflectIsExtensible(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.isExtensible should be an Object");
-    }
-
-    // 2. Return target.[[IsExtensible]]().
-    return Value(target.asObject()->isExtensible(state));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.preventextensions
-static Value builtinReflectPreventExtensions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.preventExtension should be an Object");
-    }
-
-    // 2. Return target.[[PreventExtensions]]().
-    return Value(target.asObject()->preventExtensions(state));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.ownkeys
-static Value builtinReflectOwnKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.preventExtension should be an Object");
-    }
-    // 2. Let keys be target.[[OwnPropertyKeys]]().
-    // 3. ReturnIfAbrupt(keys).
-    auto keys = target.asObject()->ownPropertyKeys(state);
-    // 4. Return CreateArrayFromList(keys).
-    return Object::createArrayFromList(state, keys.size(), keys.data());
-}
-
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.set
-static Value builtinReflectSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.set should be an Object");
-    }
-
-    // 2. Let key be ToPropertyKey(propertyKey).
-    Value key = argv[1].toPropertyKey(state);
-
-    // 4. If receiver is not present, then
-    // 4.a. Let receiver be target.
-    Value receiver = argc > 3 ? argv[3] : target;
-
-    // 5. Return target.[[Set]](key, V, receiver).
-    return Value(target.asObject()->set(state, ObjectPropertyName(state, key), argv[2], receiver));
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-reflect.setprototypeof
-static Value builtinReflectSetPrototypeOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    auto strings = &state.context()->staticStrings();
-    Value target = argv[0];
-    Value proto = argv[1];
-
-    // 1. If Type(target) is not Object, throw a TypeError exception.
-    if (!target.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The target of Reflect.setPrototypeOf should be an Object");
-    }
-
-    // 2. If Type(proto) is not Object and proto is not null, throw a TypeError exception
-    if (!proto.isObject() && !proto.isNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->Reflect.string(), false, String::emptyString, "%s: The proto of Reflect.setPrototypeOf should be an Object or Null");
-    }
-
-    // 3. Return target.[[SetPrototypeOf]](proto).
-    return Value(target.asObject()->setPrototype(state, proto));
-}
-
-void GlobalObject::installReflect(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_reflect = new Object(state);
-    m_reflect->setGlobalIntrinsicObject(state);
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().apply),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().apply, builtinReflectApply, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().construct),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().construct, builtinReflectConstruct, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().defineProperty),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().defineProperty, builtinReflectDefineProperty, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().deleteProperty),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().deleteProperty, builtinReflectDeleteProperty, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinReflectGet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().getOwnPropertyDescriptor),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getOwnPropertyDescriptor, builtinReflectGetOwnPropertyDescriptor, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().getPrototypeOf),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getPrototypeOf, builtinReflectGetPrototypeOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinReflectHas, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().isExtensible),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().isExtensible, builtinReflectIsExtensible, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().preventExtensions),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().preventExtensions, builtinReflectPreventExtensions, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().ownKeys),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().ownKeys, builtinReflectOwnKeys, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinReflectSet, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().setPrototypeOf),
-                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setPrototypeOf, builtinReflectSetPrototypeOf, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                ObjectPropertyDescriptor(state.context()->staticStrings().Reflect.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(strings->Reflect),
-                      ObjectPropertyDescriptor(m_reflect, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinRegExp.cpp
deleted file mode 100644 (file)
index 7459b0e..0000000
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "RegExpObject.h"
-#include "ArrayObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinRegExpConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value pattern = argv[0];
-    Value flags = argv[1];
-    String* source = pattern.isUndefined() ? String::emptyString : pattern.toString(state);
-    String* option = flags.isUndefined() ? String::emptyString : flags.toString(state);
-
-    // Let patternIsRegExp be IsRegExp(pattern).
-    bool patternIsRegExp = argv[0].isObject() && argv[0].asObject()->isRegExp(state);
-
-    if (!newTarget.hasValue()) {
-        // Let newTarget be the active function object.
-        newTarget = state.resolveCallee();
-        // If patternIsRegExp is true and flags is undefined, then
-        if (patternIsRegExp && flags.isUndefined()) {
-            // Let patternConstructor be Get(pattern, "constructor").
-            Value patternConstructor = pattern.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().constructor)).value(state, pattern);
-            // If SameValue(patternConstructor, newTarget), then return pattern.
-            if (patternConstructor.isObject() && patternConstructor.asObject() == newTarget.value()) {
-                return pattern;
-            }
-        }
-    }
-
-    // If Type(pattern) is Object and pattern has a [[RegExpMatcher]] internal slot, then
-    if (pattern.isObject() && pattern.asObject()->isRegExpObject()) {
-        RegExpObject* patternRegExp = pattern.asObject()->asRegExpObject();
-        // Let P be the value of pattern’s [[OriginalSource]] internal slot.
-        source = patternRegExp->source();
-        // If flags is undefined, let F be the value of pattern’s [[OriginalFlags]] internal slot.
-        // Else, let F be flags.
-        option = flags.isUndefined() ? patternRegExp->optionString(state) : flags.toString(state);
-    } else if (patternIsRegExp) {
-        Value P = pattern.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().source)).value(state, pattern);
-        source = P.isUndefined() ? String::emptyString : P.toString(state);
-        if (flags.isUndefined()) {
-            Value F = pattern.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, pattern);
-            option = F.isUndefined() ? String::emptyString : F.toString(state);
-        }
-    }
-
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->regexpPrototype();
-    });
-    RegExpObject* regexp = new RegExpObject(state, proto, source, option);
-
-    if (newTarget != state.context()->globalObject()->regexp()) {
-        regexp->setLegacyFeaturesEnabled(false);
-    }
-
-    // TODO http://www.ecma-international.org/ecma-262/6.0/index.html#sec-escaperegexppattern
-    return regexp;
-}
-
-static Value builtinRegExpExec(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, RegExp, exec);
-    if (!thisObject->isRegExpObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().exec.string(), ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-    }
-    RegExpObject* regexp = thisObject->asRegExpObject();
-    unsigned int option = regexp->option();
-    String* str = argv[0].toString(state);
-    uint64_t lastIndex = 0;
-    if (option & (RegExpObject::Global | RegExpObject::Sticky)) {
-        lastIndex = regexp->computedLastIndex(state);
-        if (lastIndex > str->length()) {
-            regexp->setLastIndex(state, Value(0));
-            return Value(Value::Null);
-        }
-    } else {
-        // dummy get lastIndex
-        regexp->computedLastIndex(state);
-    }
-
-    RegexMatchResult result;
-    if (regexp->matchNonGlobally(state, str, result, false, lastIndex)) {
-        int e = result.m_matchResults[0][0].m_end;
-        if (option & RegExpObject::Option::Unicode) {
-            char16_t utfRes = str->charAt(e);
-            size_t eUTF = str->find(new ASCIIString((const char*)&utfRes), 0);
-            if (eUTF >= str->length()) {
-                e = str->length();
-            } else if ((int)eUTF > e || e == (int)str->length()) {
-                e = eUTF;
-            }
-        }
-
-        if (option & (RegExpObject::Option::Sticky | RegExpObject::Option::Global)) {
-            regexp->setLastIndex(state, Value(e));
-        }
-
-        return regexp->createRegExpMatchedArray(state, result, str);
-    }
-
-    if (option & (RegExpObject::Option::Sticky | RegExpObject::Option::Global)) {
-        regexp->setLastIndex(state, Value(0));
-    }
-
-    return Value(Value::Null);
-}
-
-static Value regExpExec(ExecutionState& state, Object* R, String* S)
-{
-    ASSERT(R->isObject());
-    ASSERT(S->isString());
-    Value exec = R->get(state, ObjectPropertyName(state.context()->staticStrings().exec)).value(state, R);
-    Value arg[1] = { S };
-    if (exec.isCallable()) {
-        Value result = Object::call(state, exec, R, 1, arg);
-        if (result.isNull() || result.isObject()) {
-            return result;
-        }
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().test.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    return builtinRegExpExec(state, R, 1, arg, nullptr);
-}
-
-static Value builtinRegExpTest(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, RegExp, test);
-    if (!thisObject->isRegExpObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().test.string(), ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-    }
-    RegExpObject* regexp = thisObject->asRegExpObject();
-    unsigned int option = regexp->option();
-    String* str = argv[0].toString(state);
-    uint64_t lastIndex = 0;
-    if (option & (RegExpObject::Global | RegExpObject::Sticky)) {
-        lastIndex = regexp->computedLastIndex(state);
-        if (lastIndex > str->length()) {
-            regexp->setLastIndex(state, Value(0));
-            return Value(false);
-        }
-    }
-
-    RegexMatchResult result;
-    bool testResult = regexp->match(state, str, result, true, lastIndex);
-    return Value(testResult);
-}
-
-static Value builtinRegExpToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-
-    Object* thisObject = thisValue.asObject();
-    StringBuilder builder;
-    String* pattern = thisObject->get(state, state.context()->staticStrings().source).value(state, thisObject).toString(state);
-    Value flagsValue = thisObject->get(state, state.context()->staticStrings().flags).value(state, thisObject);
-
-    builder.appendString("/");
-    builder.appendString(pattern);
-    builder.appendString("/");
-
-    if (!flagsValue.isUndefined()) {
-        builder.appendString(flagsValue.toString(state));
-    } else {
-        builder.appendString("\0");
-    }
-
-    return builder.finalize(&state);
-}
-
-static Value builtinRegExpCompile(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isRegExpObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-    }
-
-    if (argv[0].isObject() && argv[0].asObject()->isRegExpObject()) {
-        if (!argv[1].isUndefined()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot supply flags when constructing one RegExp from another");
-        } else {
-            RegExpObject* retVal = thisValue.asPointerValue()->asObject()->asRegExpObject();
-            RegExpObject* patternRegExp = argv[0].asPointerValue()->asObject()->asRegExpObject();
-            if (patternRegExp->regexpOptionString() != nullptr) {
-                retVal->init(state, patternRegExp->source(), patternRegExp->regexpOptionString());
-            } else {
-                retVal->init(state, patternRegExp->source());
-            }
-            return retVal;
-        }
-    }
-
-    RegExpObject* retVal = thisValue.asPointerValue()->asObject()->asRegExpObject();
-    String* pattern_str = argv[0].isUndefined() ? String::emptyString : argv[0].toString(state);
-    String* flags_str = argv[1].isUndefined() ? String::emptyString : argv[1].toString(state);
-    retVal->init(state, pattern_str, flags_str);
-    return retVal;
-}
-static Value builtinRegExpSearch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // $21.2.5.9 RegExp.prototype[@@search]
-    RESOLVE_THIS_BINDING_TO_OBJECT(rx, Object, search);
-    String* s = argv[0].toString(state);
-    Value previousLastIndex = rx->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, thisValue);
-    if (!previousLastIndex.equalsToByTheSameValueAlgorithm(state, Value(0))) {
-        rx->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), Value(0), thisValue);
-    }
-    Value result = regExpExec(state, rx, s);
-
-    Value currentLastIndex = rx->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, thisValue);
-    if (!previousLastIndex.equalsToByTheSameValueAlgorithm(state, currentLastIndex)) {
-        rx->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), previousLastIndex, thisValue);
-    }
-    if (result.isNull()) {
-        return Value(-1);
-    } else {
-        return result.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, thisValue);
-    }
-}
-
-// $21.2.5.11 RegExp.prototype[@@split]
-static Value builtinRegExpSplit(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-    Object* rx = thisValue.asObject();
-    String* S = argv[0].toString(state);
-
-    // Let C be SpeciesConstructor(rx, %RegExp%).
-    Value C = rx->speciesConstructor(state, state.context()->globalObject()->regexp());
-
-    // Let flags be ToString(Get(rx, "flags")).
-    String* flags = rx->get(state, ObjectPropertyName(state.context()->staticStrings().flags)).value(state, rx).toString(state);
-    bool unicodeMatching = false;
-
-    String* newFlags;
-    // If flags contains "u", let unicodeMatching be true.
-    if (flags->find("u") != SIZE_MAX) {
-        unicodeMatching = true;
-    }
-
-    // If flags contains "y", let newFlags be flags.
-    // Else, let newFlags be the string that is the concatenation of flags and "y".
-    StringBuilder builder;
-    builder.appendString(flags);
-    if (flags->find("y") == SIZE_MAX) {
-        builder.appendString("y");
-    }
-    newFlags = builder.finalize();
-
-    // Let splitter be Construct(C, <<rx, newFlags>>).
-    Value params[2] = { rx, newFlags };
-    Object* splitter = Object::construct(state, C, 2, params).toObject(state);
-
-    // Let A be ArrayCreate(0).
-    ArrayObject* A = new ArrayObject(state);
-
-    // Let lengthA be 0.
-    size_t lengthA = 0;
-    // If limit is undefined, let lim be 2^53–1; else let lim be ToLength(limit).
-    // Note: using toUint32() here since toLength() returns 0 for negative values, which leads to incorrect behavior.
-    uint64_t lim = argc > 1 && !argv[1].isUndefined() ? argv[1].toUint32(state) : (1ULL << 53) - 1;
-
-    // Let size be the number of elements in S.
-    size_t size = S->length();
-    // Let p be 0.
-    size_t p = 0;
-    // If lim = 0, return A.
-    if (lim == 0) {
-        return A;
-    }
-
-    Value z;
-    // If size = 0, then
-    if (size == 0) {
-        // Let z be RegExpExec(splitter, S).
-
-        Value z = regExpExec(state, splitter, S);
-        // If z is not null, return A.
-        if (!z.isNull()) {
-            return A;
-        }
-        // Perform CreateDataProperty(A, "0", S).
-        A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, (ObjectPropertyDescriptor::AllPresent)));
-        // Return A.
-        return A;
-    }
-
-    // Let q be p.
-    size_t q = p;
-    // Repeat, while q < size.
-    while (q < size) {
-        // Let setStatus be Set(splitter, "lastIndex", q, true).
-        splitter->setThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lastIndex), Value(q), splitter);
-        // Let z be RegExpExec(splitter, S).
-        Value z = regExpExec(state, splitter, S);
-        // If z is null, let q be AdvanceStringIndex(S, q, unicodeMatching).
-        if (z.isNull()) {
-            q = S->advanceStringIndex(q, unicodeMatching);
-        } else {
-            // Else z is not null,
-            // Let e be ToLength(Get(splitter, "lastIndex")).
-            size_t e = splitter->get(state, ObjectPropertyName(state.context()->staticStrings().lastIndex)).value(state, splitter).toLength(state);
-            if (e > size) {
-                e = size;
-            }
-            // If e = p, let q be AdvanceStringIndex(S, q, unicodeMatching).
-            if (e == p) {
-                q = S->advanceStringIndex(q, unicodeMatching);
-            } else {
-                // Else e != p
-                size_t matchStart = z.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, z).toNumber(state);
-
-                if (matchStart >= S->length()) {
-                    matchStart = p;
-                }
-                // Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through q (exclusive).
-                String* T = S->substring(p, matchStart);
-                // Perform CreateDataProperty(A, ToString(lengthA), T).
-                A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(T, (ObjectPropertyDescriptor::AllPresent)));
-                // Let lengthA be lengthA + 1.
-                lengthA++;
-                // If lengthA = lim, return A.
-                if (lengthA == lim) {
-                    return A;
-                }
-                // Let p be e.
-                p = e;
-                // Let numberOfCaptures be ToLength(Get(z, "length")).
-                size_t numberOfCaptures = z.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, z).toLength(state);
-                // Let numberOfCaptures be max(numberOfCaptures - 1, 0).
-                numberOfCaptures = std::max(numberOfCaptures - 1, (size_t)0);
-                if (numberOfCaptures == SIZE_MAX) {
-                    numberOfCaptures = 0;
-                }
-                // Let i be 1.
-                // Repeat, while i <= numberOfCaptures.
-                for (size_t i = 1; i <= numberOfCaptures; i++) {
-                    // Let nextCapture be Get(z, ToString(i)).
-                    Value nextCapture = z.asObject()->get(state, ObjectPropertyName(state, Value(i).toString(state))).value(state, z);
-                    // Perform CreateDataProperty(A, ToString(lengthA), nextCapture).
-                    A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(nextCapture, ObjectPropertyDescriptor::AllPresent));
-                    // Let lengthA be lengthA + 1.
-                    lengthA++;
-                    // If lengthA = lim, return A.
-                    if (lengthA == lim) {
-                        return A;
-                    }
-                }
-                // Let q be p.
-                q = p;
-            }
-        }
-    }
-
-    // Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through size (exclusive).
-    String* T = S->substring(p, size);
-    // Perform CreateDataProperty(A, ToString(lengthA), T ).
-    A->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(lengthA).toString(state)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
-    // Return A.
-    return A;
-}
-
-static Value builtinRegExpReplace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ASSERT(argc == 0 || argv != nullptr);
-    Value rx = thisValue;
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-    String* str = argv[0].toString(state);
-    Value replaceValue = argv[1];
-    size_t lengthStr = str->length();
-    bool functionalReplace = replaceValue.isCallable();
-    bool fullUnicode = false;
-    String* replacement = String::emptyString;
-    size_t nextSourcePosition = 0;
-    StringBuilder builder;
-
-    if (!functionalReplace) {
-        replaceValue = replaceValue.toString(state);
-    }
-    bool global = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().global)).value(state, rx).toBoolean(state);
-    if (global) {
-        fullUnicode = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().unicode)).value(state, rx).toBoolean(state);
-        rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(0), rx);
-    }
-    ValueVectorWithInlineStorage results;
-    Value strValue = Value(str);
-    while (true) {
-        Value result = regExpExec(state, rx.toObject(state), str);
-        if (result.isNull()) {
-            break;
-        }
-        results.push_back(result);
-        if (!global) {
-            break;
-        }
-        Value matchStr = result.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, result);
-        if (matchStr.toString(state)->length() == 0 && global) {
-            uint64_t thisIndex = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, rx).toLength(state);
-            uint64_t nextIndex = str->advanceStringIndex(thisIndex, fullUnicode);
-            rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(nextIndex), rx);
-        }
-    }
-
-    size_t resultSize = results.size();
-    for (uint i = 0; i < resultSize; i++) {
-        Object* result = results[i].toObject(state);
-        size_t nCaptures = result->get(state, ObjectPropertyName(state.context()->staticStrings().length)).value(state, result).toLength(state) - 1;
-
-        if (nCaptures == SIZE_MAX) {
-            nCaptures = 0;
-        }
-        String* matched = result->get(state, ObjectPropertyName(state, Value(0))).value(state, result).toString(state);
-        size_t matchLength = matched->length();
-        size_t position = result->get(state, ObjectPropertyName(state.context()->staticStrings().index)).value(state, result).toInteger(state);
-
-        if (position > lengthStr) {
-            position = lengthStr;
-        }
-        if (position == SIZE_MAX) {
-            position = 0;
-        }
-        size_t n = 1;
-        StringVector captures;
-        Value* replacerArgs = nullptr;
-        Value namedCaptures = result->get(state, ObjectPropertyName(state, state.context()->staticStrings().groups)).value(state, result);
-        size_t replacerArgsSize = nCaptures + 3;
-        if (functionalReplace) {
-            if (namedCaptures.isUndefined()) {
-                replacerArgs = ALLOCA(sizeof(Value) * (nCaptures + 3), Value, state);
-            } else {
-                replacerArgs = ALLOCA(sizeof(Value) * (nCaptures + 4), Value, state);
-                replacerArgsSize++;
-                replacerArgs[nCaptures + 3] = namedCaptures;
-            }
-            replacerArgs[0] = matched;
-        }
-        while (n <= nCaptures) {
-            Value capN = result->get(state, ObjectPropertyName(state, Value(n))).value(state, result);
-            if (!capN.isUndefined()) {
-                captures.push_back(capN.toString(state));
-            } else {
-                captures.push_back(String::emptyString);
-            }
-            if (functionalReplace) {
-                replacerArgs[n] = capN;
-            }
-            n++;
-        }
-        if (functionalReplace) {
-            replacerArgs[nCaptures + 1] = Value((size_t)position);
-            replacerArgs[nCaptures + 2] = Value(str);
-
-            replacement = Object::call(state, replaceValue, Value(), replacerArgsSize, replacerArgs).toString(state);
-        } else {
-            replacement = String::getSubstitution(state, matched, str, position, captures, namedCaptures, replaceValue.toString(state));
-        }
-        if (position >= nextSourcePosition) {
-            builder.appendSubString(str, nextSourcePosition, position);
-            builder.appendSubString(replacement, 0, replacement->length());
-            nextSourcePosition = position + matchLength;
-        }
-    }
-    if (nextSourcePosition >= lengthStr) {
-        return Value(builder.finalize(&state));
-    }
-    builder.appendSubString(str, nextSourcePosition, str->length());
-    return Value(builder.finalize(&state));
-}
-
-static Value builtinRegExpMatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value rx = thisValue;
-
-    if (!rx.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true,
-                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-
-    String* str = argv[0].toString(state);
-    ASSERT(str != nullptr);
-
-    //21.2.5.6.8
-    bool global = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().global)).value(state, rx).toBoolean(state);
-
-    if (!global) {
-        return regExpExec(state, rx.asObject(), str);
-    }
-
-    bool fullUnicode = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().unicode)).value(state, rx).toBoolean(state);
-    rx.asObject()->setThrowsException(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex), Value(0), rx);
-    ArrayObject* A = new ArrayObject(state);
-    size_t n = 0;
-
-    //21.2.5.6.8.g.i
-    while (true) {
-        //21.2.5.6.8.g.i
-        Value result = regExpExec(state, rx.asObject(), str);
-        //21.2.5.6.8.g.iii
-        if (result.isNull()) {
-            if (n == 0) {
-                return Value(Value::Null);
-            }
-            return A;
-        } else {
-            //21.2.5.6.8.g.iv
-            Value matchStr = result.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, result).toString(state);
-            A->defineOwnProperty(state, ObjectPropertyName(state, Value(n).toString(state)), ObjectPropertyDescriptor(Value(matchStr), (ObjectPropertyDescriptor::PresentAttribute::AllPresent)));
-            if (matchStr.asString()->length() == 0) {
-                //21.2.5.6.8.g.iv.5
-                uint64_t thisIndex = rx.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, rx).toLength(state);
-                uint64_t nextIndex = str->advanceStringIndex(thisIndex, fullUnicode);
-                rx.asObject()->setThrowsException(state, state.context()->staticStrings().lastIndex, Value(nextIndex), rx);
-            }
-            n++;
-        }
-    }
-}
-
-static Value builtinRegExpMatchAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExp.string(), true,
-                                       state.context()->staticStrings().toPrimitive.string(), ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-    bool global = false;
-    bool unicode = false;
-    Object* thisObj = thisValue.asObject();
-    String* s = argv[0].toString(state);
-    String* flags = thisObj->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, thisObj).toString(state);
-
-    Value c = thisObj->speciesConstructor(state, state.context()->globalObject()->regexp());
-    Value arguments[] = { thisObj, flags };
-    Object* matcher = Object::construct(state, c, 2, arguments).toObject(state);
-
-    size_t lastIndex = thisObj->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, thisObj).toNumber(state);
-    matcher->asRegExpObject()->setLastIndex(state, Value(lastIndex));
-
-    if (flags->find("g") != SIZE_MAX) {
-        global = true;
-    }
-    if (flags->find("u") != SIZE_MAX) {
-        unicode = true;
-    }
-    return new RegExpStringIteratorObject(state, global, unicode, matcher->asRegExpObject(), s);
-}
-
-
-static Value builtinRegExpOptionGetterHelper(ExecutionState& state, Value thisValue, unsigned int option)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-
-    if (!thisValue.asObject()->isRegExpObject()) {
-        if (thisValue.asObject() == state.context()->globalObject()->regexpPrototype()) {
-            return Value();
-        } else {
-            ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-        }
-    }
-
-    return Value((bool)(thisValue.asObject()->asRegExpObject()->option() & option));
-}
-
-static Value builtinRegExpFlagsGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, "getter called on non-object");
-    }
-
-    return Value(thisValue.asObject()->optionString(state));
-}
-
-static Value builtinRegExpGlobalGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Global);
-}
-
-static Value builtinRegExpDotAllGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::DotAll);
-}
-
-static Value builtinRegExpIgnoreCaseGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::IgnoreCase);
-}
-
-static Value builtinRegExpMultiLineGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::MultiLine);
-}
-
-static Value builtinRegExpSourceGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject);
-    }
-
-    if (!thisValue.asObject()->isRegExpObject()) {
-        if (thisValue.asObject() == state.context()->globalObject()->regexpPrototype()) {
-            return Value(state.context()->staticStrings().defaultRegExpString.string());
-        } else {
-            ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-        }
-    }
-
-    return Value(thisValue.asObject()->asRegExpObject()->source());
-}
-
-static Value builtinRegExpStickyGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Sticky);
-}
-
-static Value builtinRegExpUnicodeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    return builtinRegExpOptionGetterHelper(state, thisValue, RegExpObject::Option::Unicode);
-}
-
-
-// Legacy RegExp Features (non-standard)
-static Value builtinRegExpInputGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-    }
-    auto& status = state.context()->regexpLegacyFeatures();
-    if (!status.isValid()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);
-    }
-    return status.input;
-}
-
-static Value builtinRegExpInputSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);
-    }
-    state.context()->regexpLegacyFeatures().input = argv[0].toString(state);
-    return Value();
-}
-
-#define REGEXP_LEGACY_FEATURES(F) \
-    F(LastMatch, lastMatch)       \
-    F(LastParen, lastParen)       \
-    F(LeftContext, leftContext)   \
-    F(RightContext, rightContext)
-
-#define REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(F) \
-    F(1)                                        \
-    F(2)                                        \
-    F(3)                                        \
-    F(4)                                        \
-    F(5)                                        \
-    F(6)                                        \
-    F(7)                                        \
-    F(8)                                        \
-    F(9)
-
-#define DEFINE_LEGACY_FEATURE_GETTER(NAME, name)                                                                                            \
-    static Value builtinRegExp##NAME##Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                       \
-        if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {                                   \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);         \
-        }                                                                                                                                   \
-                                                                                                                                            \
-        auto& status = state.context()->regexpLegacyFeatures();                                                                             \
-        if (!status.isValid()) {                                                                                                            \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);               \
-        }                                                                                                                                   \
-        return new StringView(status.name);                                                                                                 \
-    }
-
-#define DEFINE_LEGACY_DOLLAR_NUMBER_FEATURE_GETTER(number)                                                                                          \
-    static Value builtinRegExpDollar##number##Getter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                               \
-        if (!thisValue.isObject() || thisValue.asObject() != state.context()->globalObject()->regexp()) {                                           \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotRegExpObject);                 \
-        }                                                                                                                                           \
-        auto& status = state.context()->regexpLegacyFeatures();                                                                                     \
-        if (!status.isValid()) {                                                                                                                    \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::String_InvalidStringLength);                       \
-        }                                                                                                                                           \
-        return (status.dollarCount < number) ? String::emptyString : new StringView(status.dollars[number - 1]);                                    \
-    }
-
-REGEXP_LEGACY_FEATURES(DEFINE_LEGACY_FEATURE_GETTER);
-REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(DEFINE_LEGACY_DOLLAR_NUMBER_FEATURE_GETTER);
-
-static Value builtinRegExpStringIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isRegExpStringIteratorObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().RegExpStringIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    RegExpStringIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asRegExpStringIteratorObject();
-    return iter->next(state);
-}
-
-std::pair<Value, bool> RegExpStringIteratorObject::advance(ExecutionState& state)
-{
-    if (m_isDone) {
-        return std::make_pair(Value(), true);
-    }
-    RegExpObject* r = m_regexp;
-    String* s = m_string;
-    bool global = m_isGlobal;
-    bool unicode = m_isUnicode;
-    Value match = regExpExec(state, r, s);
-
-    if (match.isNull()) {
-        m_isDone = true;
-        return std::make_pair(Value(), true);
-    }
-    if (global) {
-        String* matchStr = match.asObject()->get(state, ObjectPropertyName(state, Value(0))).value(state, match).toString(state);
-        if (matchStr->length() == 0) {
-            //21.2.5.6.8.g.iv.5
-            uint64_t thisIndex = r->get(state, ObjectPropertyName(state, state.context()->staticStrings().lastIndex)).value(state, r).toLength(state);
-            uint64_t nextIndex = s->advanceStringIndex(thisIndex, unicode);
-            r->setThrowsException(state, state.context()->staticStrings().lastIndex, Value(nextIndex), r);
-        }
-        return std::make_pair(match, false);
-    }
-    m_isDone = true;
-    return std::make_pair(match, false);
-}
-
-void GlobalObject::installRegExp(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    m_regexp = new NativeFunctionObject(state, NativeFunctionInfo(strings->RegExp, builtinRegExpConstructor, 2), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_regexp->setGlobalIntrinsicObject(state);
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexp->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    // Legacy RegExp Features (non-standard)
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpInputGetter, 0, NativeFunctionInfo::Strict)),
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->set, builtinRegExpInputSetter, 1, NativeFunctionInfo::Strict)));
-        m_regexp->defineOwnProperty(state, strings->input, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-        m_regexp->defineOwnProperty(state, strings->$_, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLastMatchGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        m_regexp->defineOwnProperty(state, strings->lastMatch, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-        m_regexp->defineOwnProperty(state, strings->$Ampersand, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLastParenGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        m_regexp->defineOwnProperty(state, strings->lastParen, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-        m_regexp->defineOwnProperty(state, strings->$PlusSign, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpLeftContextGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        m_regexp->defineOwnProperty(state, strings->leftContext, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-        m_regexp->defineOwnProperty(state, strings->$GraveAccent, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    }
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpRightContextGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        m_regexp->defineOwnProperty(state, strings->rightContext, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-        m_regexp->defineOwnProperty(state, strings->$Apostrophe, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    }
-
-#define DEFINE_LEGACY_DOLLAR_NUMBER_ATTR(number)                                                                                                                                           \
-    {                                                                                                                                                                                      \
-        JSGetterSetter gs(                                                                                                                                                                 \
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->get, builtinRegExpDollar##number##Getter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));              \
-        m_regexp->defineOwnProperty(state, strings->$##number, ObjectPropertyDescriptor(gs, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent))); \
-    }
-
-    REGEXP_LEGACY_DOLLAR_NUMBER_FEATURES(DEFINE_LEGACY_DOLLAR_NUMBER_ATTR);
-
-    m_regexpPrototype = new Object(state);
-    m_regexpPrototype->setGlobalIntrinsicObject(state, true);
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFlags, builtinRegExpFlagsGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->flags), desc);
-    }
-
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getGlobal, builtinRegExpGlobalGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->global), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getDotAll, builtinRegExpDotAllGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->dotAll), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getIgnoreCase, builtinRegExpIgnoreCaseGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->ignoreCase), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getMultiline, builtinRegExpMultiLineGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->multiline), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getSource, builtinRegExpSourceGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->source), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getSticky, builtinRegExpStickyGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->sticky), desc);
-    }
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(strings->getUnicode, builtinRegExpUnicodeGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->unicode), desc);
-    }
-
-    m_regexpPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_regexp->setFunctionPrototype(state, m_regexpPrototype);
-
-    // $21.2.5.2 RegExp.prototype.exec
-    m_regexpExecMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->exec, builtinRegExpExec, 1, NativeFunctionInfo::Strict));
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->exec),
-                                                        ObjectPropertyDescriptor(m_regexpExecMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $21.2.5.13 RegExp.prototype.test
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->test),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->test, builtinRegExpTest, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $21.2.5.14 RegExp.prototype.toString
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinRegExpToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    // $B.2.5.1 RegExp.prototype.compile
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->compile),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->compile, builtinRegExpCompile, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.2.5.9 RegExp.prototype[@@search]
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolSearch, builtinRegExpSearch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.2.5.11 RegExp.prototype[@@split]
-    m_regexpSplitMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolSplit, builtinRegExpSplit, 2, NativeFunctionInfo::Strict));
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().split),
-                                                        ObjectPropertyDescriptor(m_regexpSplitMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.2.5.8 RegExp.prototype [@@replace]
-    m_regexpReplaceMethod = new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolReplace, builtinRegExpReplace, 2, NativeFunctionInfo::Strict));
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace),
-                                                        ObjectPropertyDescriptor(m_regexpReplaceMethod, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.2.5.6 RegExp.prototype[@@match]
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolMatch, builtinRegExpMatch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_regexpPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->symbolMatchAll, builtinRegExpMatchAll, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_regexpStringIteratorPrototype = new Object(state, m_iteratorPrototype);
-    m_regexpStringIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_regexpStringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                                      ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinRegExpStringIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_regexpStringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                      ObjectPropertyDescriptor(Value(String::fromASCII("RegExp String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(strings->RegExp),
-                      ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSet.cpp
deleted file mode 100644 (file)
index 6daab51..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "SetObject.h"
-#include "IteratorObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, throw a TypeError exception.
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    // Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%SetPrototype%", « [[SetData]] »).
-    // Set set's [[SetData]] internal slot to a new empty List.
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->setPrototype();
-    });
-    SetObject* set = new SetObject(state, proto);
-
-    // If iterable is not present, let iterable be undefined.
-    Value iterable;
-    if (argc >= 1) {
-        iterable = argv[0];
-    }
-
-    // If iterable is either undefined or null, return set.
-    if (iterable.isUndefinedOrNull()) {
-        return set;
-    }
-
-    // Let adder be ? Get(set, "add").
-    Value adder = set->get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set);
-    // If IsCallable(adder) is false, throw a TypeError exception.
-    if (!adder.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
-    }
-    // Let iteratorRecord be ? GetIterator(iterable).
-    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
-
-    // Repeat
-    while (true) {
-        // Let next be ? IteratorStep(iteratorRecord).
-        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
-        // If next is false, return set.
-        if (!next.hasValue()) {
-            return set;
-        }
-        // Let nextValue be ? IteratorValue(next).
-        Value nextValue = IteratorObject::iteratorValue(state, next.value());
-
-        // Let status be Call(adder, set, « nextValue »).
-        try {
-            Value argv[1] = { nextValue };
-            Object::call(state, adder, set, 1, argv);
-        } catch (const Value& v) {
-            // we should save thrown value bdwgc cannot track thrown value
-            Value exceptionValue = v;
-            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
-            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-        }
-    }
-
-    return set;
-}
-
-#define RESOLVE_THIS_BINDING_TO_SET(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                          \
-    if (!thisValue.isObject() || !thisValue.asObject()->isSetObject()) {                                                                                                                                                                                 \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                    \
-    SetObject* NAME = thisValue.asObject()->asSetObject();
-
-static Value builtinSetAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, add);
-    S->add(state, argv[0]);
-    return S;
-}
-
-static Value builtinSetClear(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, clear);
-    S->clear(state);
-    return Value();
-}
-
-static Value builtinSetDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, stringDelete);
-    return Value(S->deleteOperation(state, argv[0]));
-}
-
-static Value builtinSetHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, has);
-    return Value(S->has(state, argv[0]));
-}
-
-static Value builtinSetForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let S be the this value.
-    // If Type(S) is not Object, throw a TypeError exception.
-    // If S does not have a [[SetData]] internal slot, throw a TypeError exception.
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, forEach);
-
-    Value callbackfn = argv[0];
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Set.string(), true, state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc >= 2) {
-        T = argv[1];
-    }
-    // Let entries be the List that is the value of S's [[SetData]] internal slot.
-    const SetObject::SetObjectData& entries = S->storage();
-    // Repeat for each e that is an element of entries, in original insertion order
-    for (size_t i = 0; i < entries.size(); i++) {
-        Value e = entries[i];
-        // If e is not empty, then
-        if (!e.isEmpty()) {
-            // If e.[[Key]] is not empty, then
-            // Perform ? Call(callbackfn, T, « e, e, S »).
-            Value argv[3] = { Value(e), Value(e), Value(S) };
-            Object::call(state, callbackfn, T, 3, argv);
-        }
-    }
-
-    return Value();
-}
-
-static Value builtinSetValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, values);
-    return S->values(state);
-}
-
-static Value builtinSetEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, entries);
-    return S->entries(state);
-}
-
-static Value builtinSetSizeGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SET(S, Set, size);
-    return Value(S->size(state));
-}
-
-static Value builtinSetIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isSetIteratorObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SetIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    SetIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asSetIteratorObject();
-    return iter->next(state);
-}
-
-void GlobalObject::installSet(ExecutionState& state)
-{
-    m_set = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Set, builtinSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_set->setGlobalIntrinsicObject(state);
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_set->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    m_setPrototype = new Object(state);
-    m_setPrototype->setGlobalIntrinsicObject(state, true);
-    m_setPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().clear),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinSetClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().forEach),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinSetForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    auto valuesFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinSetValues, 0, NativeFunctionInfo::Strict));
-    auto values = ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().values), values);
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().keys), values);
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().entries),
-                                                     ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinSetEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                     ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                     ObjectPropertyDescriptor(Value(state.context()->staticStrings().Set.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-    JSGetterSetter gs(
-        new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("get size")), builtinSetSizeGetter, 0, NativeFunctionInfo::Strict)),
-        Value(Value::EmptyValue));
-    ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-    m_setPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);
-
-    m_setIteratorPrototype = new Object(state, m_iteratorPrototype);
-    m_setIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_setIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                             ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinSetIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_setIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                             ObjectPropertyDescriptor(Value(String::fromASCII("Set Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_set->setFunctionPrototype(state, m_setPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Set),
-                      ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSharedArrayBuffer.cpp
deleted file mode 100644 (file)
index 1aaba1c..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#if defined(ENABLE_THREADING)
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "NativeFunctionObject.h"
-#include "ArrayBufferObject.h"
-#include "SharedArrayBufferObject.h"
-
-namespace Escargot {
-
-// https://262.ecma-international.org/#sec-sharedarraybuffer-constructor
-static Value builtinSharedArrayBufferConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    uint64_t byteLength = argv[0].toIndex(state);
-    if (byteLength == Value::InvalidIndexValue) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().SharedArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
-    }
-
-    return SharedArrayBufferObject::allocateSharedArrayBuffer(state, newTarget.value(), byteLength);
-}
-
-// https://262.ecma-international.org/#sec-get-sharedarraybuffer.prototype.bytelength
-static Value builtinSharedArrayBufferByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isSharedArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().getbyteLength.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    SharedArrayBufferObject* obj = thisValue.asObject()->asSharedArrayBufferObject();
-    return Value(obj->byteLength());
-}
-
-// https://262.ecma-international.org/#sec-sharedarraybuffer.prototype.slice
-static Value builtinSharedArrayBufferSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isSharedArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-
-    SharedArrayBufferObject* O = thisValue.asObject()->asSharedArrayBufferObject();
-    double len = O->byteLength();
-    double relativeStart = argv[0].toInteger(state);
-    size_t first = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, len);
-    double relativeEnd = argv[1].isUndefined() ? len : argv[1].toInteger(state);
-    double final_ = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, len);
-    size_t newLen = std::max((int)final_ - (int)first, 0);
-
-    Value constructor = O->speciesConstructor(state, state.context()->globalObject()->sharedArrayBuffer());
-    Value arguments[] = { Value(newLen) };
-    Object* newValue = Object::construct(state, constructor, 1, arguments).toObject(state);
-    if (!newValue->isSharedArrayBufferObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor SharedArrayBuffer is not valid SharedArrayBuffer");
-    }
-
-    SharedArrayBufferObject* newBuffer = newValue->asSharedArrayBufferObject();
-    if ((newBuffer->data() == O->data()) || (newBuffer->byteLength() < newLen)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().SharedArrayBuffer.string(), true, state.context()->staticStrings().slice.string(), "%s: return value of constructor SharedArrayBuffer is not valid SharedArrayBuffer");
-    }
-
-    newBuffer->fillData(O->data() + first, newLen);
-    return newBuffer;
-}
-
-void GlobalObject::installSharedArrayBuffer(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    m_sharedArrayBuffer = new NativeFunctionObject(state, NativeFunctionInfo(strings->SharedArrayBuffer, builtinSharedArrayBufferConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_sharedArrayBuffer->setGlobalIntrinsicObject(state);
-
-    m_sharedArrayBufferPrototype = new Object(state, m_objectPrototype);
-    m_sharedArrayBufferPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_sharedArrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    m_sharedArrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                   ObjectPropertyDescriptor(Value(strings->SharedArrayBuffer.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_sharedArrayBuffer->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-    JSGetterSetter gs(
-        new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinSharedArrayBufferByteLengthGetter, 0, NativeFunctionInfo::Strict)),
-        Value(Value::EmptyValue));
-    ObjectPropertyDescriptor byteLengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-    m_sharedArrayBufferPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc);
-    m_sharedArrayBufferPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
-                                                                   ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinSharedArrayBufferSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_sharedArrayBuffer->setFunctionPrototype(state, m_sharedArrayBufferPrototype);
-
-    defineOwnProperty(state, ObjectPropertyName(strings->SharedArrayBuffer),
-                      ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
-
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinString.cpp
deleted file mode 100644 (file)
index ac6e31d..0000000
+++ /dev/null
@@ -1,1833 +0,0 @@
-/*
- * Copyright (c) 2016-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "StringObject.h"
-#include "ErrorObject.h"
-#include "RegExpObject.h"
-#include "ArrayObject.h"
-#include "NativeFunctionObject.h"
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#include "Intl.h"
-#include "IntlCollator.h"
-#endif
-
-#include "WTFBridge.h"
-#include "Yarr.h"
-#include "YarrPattern.h"
-
-namespace Escargot {
-
-static Value builtinStringConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    String* s = String::emptyString;
-    if (argc > 0) {
-        Value value = argv[0];
-        if (!newTarget.hasValue() && value.isSymbol()) {
-            return value.asSymbol()->symbolDescriptiveString();
-        } else {
-            s = value.toString(state);
-        }
-    }
-    if (!newTarget.hasValue()) {
-        return s;
-    }
-
-    // StringCreate(s, ? GetPrototypeFromConstructor(NewTarget, "%StringPrototype%")).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->stringPrototype();
-    });
-    return new StringObject(state, proto, s);
-}
-
-static Value builtinStringToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isObject() && thisValue.asObject()->isStringObject()) {
-        return thisValue.asObject()->asStringObject()->primitiveValue();
-    }
-
-    if (thisValue.isString())
-        return thisValue.toString(state);
-
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().toString.string(), ErrorObject::Messages::GlobalObject_ThisNotString);
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-static Value builtinStringIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, indexOf);
-    String* searchStr = argv[0].toString(state);
-
-    Value val;
-    if (argc > 1) {
-        val = argv[1];
-    }
-    double pos;
-    if (val.isUndefined()) {
-        pos = 0;
-    } else {
-        pos = val.toInteger(state);
-    }
-    if (pos == std::numeric_limits<double>::infinity() || std::isnan(pos)) {
-        pos = std::numeric_limits<double>::quiet_NaN();
-    }
-    if (pos == -std::numeric_limits<double>::infinity()) {
-        pos = 0;
-    }
-    size_t len = str->length();
-    size_t start = std::min(std::max(pos, 0.0), (double)len);
-    size_t result = str->find(searchStr, start);
-
-    if (result == SIZE_MAX)
-        return Value(-1);
-    else
-        return Value(result);
-}
-
-static Value builtinStringLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let S be ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, lastIndexOf);
-    String* searchStr = argv[0].toString(state);
-
-    double numPos;
-    if (argc > 1) {
-        numPos = argv[1].toNumber(state);
-    } else {
-        numPos = Value().toNumber(state);
-    }
-
-    double pos;
-    // If numPos is NaN, let pos be +∞; otherwise, let pos be ToInteger(numPos).
-    if (std::isnan(numPos))
-        pos = std::numeric_limits<double>::infinity();
-    else
-        pos = numPos;
-
-    double len = S->length();
-    double start = std::min(std::max(pos, 0.0), len);
-    size_t result = S->rfind(searchStr, start);
-    if (result == SIZE_MAX) {
-        return Value(-1);
-    }
-    return Value(result);
-}
-
-static Value builtinStringLocaleCompare(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, localeCompare);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    String* That = argv[0].toString(state);
-    Value locales, options;
-
-    if (argc >= 2) {
-        locales = argv[1];
-    }
-    if (argc >= 3) {
-        options = argv[2];
-    }
-
-    Object* collator = IntlCollator::create(state, state.context(), locales, options);
-
-    return Value(IntlCollator::compare(state, collator, S, That));
-#else
-    String* That = argv[0].toString(state);
-    return Value(stringCompare(*S, *That));
-#endif
-}
-
-static Value builtinStringSubstring(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, substring);
-    if (argc == 0) {
-        return str;
-    } else {
-        int len = str->length();
-        double doubleStart = argv[0].toNumber(state);
-        Value end = argv[1];
-        double doubleEnd = (argc < 2 || end.isUndefined()) ? len : end.toNumber(state);
-        doubleStart = (std::isnan(doubleStart)) ? 0 : doubleStart;
-        doubleEnd = (std::isnan(doubleEnd)) ? 0 : doubleEnd;
-
-        double finalStart = (int)trunc(std::min(std::max(doubleStart, 0.0), (double)len));
-        double finalEnd = (int)trunc(std::min(std::max(doubleEnd, 0.0), (double)len));
-        size_t from = std::min(finalStart, finalEnd);
-        size_t to = std::max(finalStart, finalEnd);
-        ASSERT(from <= to);
-        if (to - from == 1) {
-            char16_t c = str->charAt(from);
-            if (c < ESCARGOT_ASCII_TABLE_MAX) {
-                return state.context()->staticStrings().asciiTable[c].string();
-            }
-        }
-        return str->substring(from, to);
-    }
-}
-
-static Value builtinStringMatch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-
-    Value regexp = argv[0];
-    if (!regexp.isUndefinedOrNull()) {
-        Value matcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match));
-        if (!matcher.isUndefined()) {
-            Value args[1] = { thisValue };
-            return Object::call(state, matcher, regexp, 1, args);
-        }
-    }
-
-    String* S = thisValue.toString(state);
-    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), String::emptyString);
-    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().match)).value(state, rx);
-    Value args[1] = { Value(S) };
-    return Object::call(state, func, rx, 1, args);
-}
-
-static Value builtinStringMatchAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-
-    Value regexp = argv[0];
-    if (!regexp.isUndefinedOrNull()) {
-        if (regexp.isObject() && regexp.asObject()->isRegExpObject()) {
-            String* flags = regexp.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, regexp).toString(state);
-            if (flags->find("g") == SIZE_MAX) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().match.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-            }
-        }
-        Value matcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll));
-        if (!matcher.isUndefined()) {
-            Value args[1] = { thisValue };
-            return Object::call(state, matcher, regexp, 1, args);
-        }
-    }
-    String* S = thisValue.toString(state);
-    StringBuilder builder;
-    builder.appendChar('g');
-    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), builder.finalize());
-    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().matchAll)).value(state, rx);
-    Value args[1] = { Value(S) };
-    return Object::call(state, func, rx, 1, args);
-}
-
-#if defined(ENABLE_ICU)
-static Value builtinStringNormalize(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    enum NormalizationForm {
-        NFC,
-        NFD,
-        NFKC,
-        NFKD
-    };
-
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, normalize);
-    Value argument = Value();
-    if (argc > 0) {
-        argument = argv[0];
-    }
-    NormalizationForm form = NFC;
-    if (LIKELY(!argument.isUndefined())) {
-        String* formString = argument.toString(state);
-        if (formString->equals("NFC")) {
-            form = NFC;
-        } else if (formString->equals("NFD")) {
-            form = NFD;
-        } else if (formString->equals("NFKC")) {
-            form = NFKC;
-        } else if (formString->equals("NFKD")) {
-            form = NFKD;
-        } else {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid normalization form");
-            return Value();
-        }
-    }
-    if (str->length() == 0) {
-        return Value(str);
-    }
-
-    auto utf16Str = str->toUTF16StringData();
-    UErrorCode status = U_ZERO_ERROR;
-    const UNormalizer2* normalizer = nullptr;
-    switch (form) {
-    case NFC:
-        normalizer = unorm2_getNFCInstance(&status);
-        break;
-    case NFD:
-        normalizer = unorm2_getNFDInstance(&status);
-        break;
-    case NFKC:
-        normalizer = unorm2_getNFKCInstance(&status);
-        break;
-    case NFKD:
-        normalizer = unorm2_getNFKDInstance(&status);
-        break;
-    default:
-        break;
-    }
-    if (!normalizer || U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
-        return Value();
-    }
-    int32_t normalizedStringLength = unorm2_normalize(normalizer, (const UChar*)utf16Str.data(), utf16Str.length(), nullptr, 0, &status);
-
-    if (U_FAILURE(status) && status != U_BUFFER_OVERFLOW_ERROR) {
-        // when normalize fails.
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
-        return Value();
-    }
-    UTF16StringData ret;
-    ret.resizeWithUninitializedValues(normalizedStringLength);
-    status = U_ZERO_ERROR;
-    unorm2_normalize(normalizer, (const UChar*)utf16Str.data(), utf16Str.length(), (UChar*)ret.data(), normalizedStringLength, &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "normalization fails");
-        return Value();
-    }
-    return new UTF16String(std::move(ret));
-}
-#endif // ENABLE_ICU
-
-static Value builtinStringRepeat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, repeat);
-    Value argument = argv[0];
-    int32_t repeatCount;
-    double count = argument.toInteger(state);
-    double newStringLength = str->length() * count;
-    if (count < 0 || count == std::numeric_limits<double>::infinity() || newStringLength > STRING_MAXIMUM_LENGTH) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid count number of String repeat method");
-    }
-
-    if (newStringLength == 0) {
-        return String::emptyString;
-    }
-
-    repeatCount = static_cast<int32_t>(count);
-
-    StringBuilder builder;
-    for (int i = 0; i < repeatCount; i++) {
-        builder.appendString(str);
-    }
-    return builder.finalize();
-}
-
-static Value builtinStringReplace(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replace.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-
-    Value searchValue = argv[0];
-    Value replaceValue = argv[1];
-
-    bool isSearchValueRegExp = searchValue.isPointerValue() && searchValue.asPointerValue()->isRegExpObject();
-    // we should keep fast-path while performace issue is unresolved
-    bool canUseFastPath = searchValue.isString() || (isSearchValueRegExp && searchValue.asPointerValue()->asRegExpObject()->yarrPatern()->m_captureGroupNames.size() == 0);
-    if (!searchValue.isUndefinedOrNull()) {
-        Value replacer = Object::getMethod(state, searchValue, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace));
-        if (canUseFastPath && isSearchValueRegExp && replacer.isPointerValue() && replacer.asPointerValue() == state.context()->globalObject()->regexpReplaceMethod()) {
-            auto exec = searchValue.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().exec));
-            if (!exec.hasValue() || exec.value(state, searchValue) != state.context()->globalObject()->regexpExecMethod()) {
-                // this means we cannot use fast path
-                Value parameters[2] = { thisValue, replaceValue };
-                return Object::call(state, replacer, searchValue, 2, parameters);
-            }
-        } else {
-            // this means we cannot use fast path
-            if (!replacer.isUndefined()) {
-                Value parameters[2] = { thisValue, replaceValue };
-                return Object::call(state, replacer, searchValue, 2, parameters);
-            }
-        }
-    }
-
-    String* string = thisValue.toString(state);
-    String* searchString = searchValue.toString(state);
-    bool functionalReplace = replaceValue.isCallable();
-
-    if (canUseFastPath) {
-        RegexMatchResult result;
-        String* replaceString = nullptr;
-
-        if (isSearchValueRegExp) {
-            RegExpObject* regexp = searchValue.asPointerValue()->asRegExpObject();
-            bool isGlobal = regexp->option() & RegExpObject::Option::Global;
-
-            if (isGlobal) {
-                regexp->setLastIndex(state, Value(0));
-            }
-            bool testResult = regexp->matchNonGlobally(state, string, result, false, 0);
-            if (testResult) {
-                if (isGlobal) {
-                    regexp->createRegexMatchResult(state, string, result);
-                }
-            }
-        } else {
-            size_t idx = string->find(searchString);
-            if (idx != (size_t)-1) {
-                std::vector<RegexMatchResult::RegexMatchResultPiece> piece;
-                RegexMatchResult::RegexMatchResultPiece p;
-                p.m_start = idx;
-                p.m_end = idx + searchString->length();
-                piece.push_back(std::move(p));
-                result.m_matchResults.push_back(std::move(piece));
-            }
-        }
-
-        // NOTE: replaceValue.toString should be called after searchValue.toString
-        if (!functionalReplace) {
-            replaceString = replaceValue.toString(state);
-        }
-
-        // If no occurrences of searchString were found, return string.
-        if (result.m_matchResults.size() == 0) {
-            return string;
-        }
-
-        if (functionalReplace) {
-            uint32_t matchCount = result.m_matchResults.size();
-            Value callee = replaceValue;
-
-            StringBuilder builer;
-            builer.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
-
-            for (uint32_t i = 0; i < matchCount; i++) {
-                int subLen = result.m_matchResults[i].size();
-                Value* arguments;
-                arguments = ALLOCA(sizeof(Value) * (subLen + 2), Value, state);
-                for (unsigned j = 0; j < (unsigned)subLen; j++) {
-                    if (result.m_matchResults[i][j].m_start == std::numeric_limits<unsigned>::max())
-                        arguments[j] = Value();
-                    else {
-                        StringBuilder argStrBuilder;
-                        argStrBuilder.appendSubString(string, result.m_matchResults[i][j].m_start, result.m_matchResults[i][j].m_end);
-                        arguments[j] = argStrBuilder.finalize(&state);
-                    }
-                }
-                arguments[subLen] = Value((int)result.m_matchResults[i][0].m_start);
-                arguments[subLen + 1] = string;
-                // 21.1.3.14 (11) it should be called with this as undefined
-                String* res = Object::call(state, callee, Value(), subLen + 2, arguments).toString(state);
-                builer.appendSubString(res, 0, res->length());
-
-                if (i < matchCount - 1) {
-                    builer.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
-                }
-            }
-            builer.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
-            return builer.finalize(&state);
-        } else {
-            ASSERT(replaceString);
-
-            bool hasDollar = false;
-            for (size_t i = 0; i < replaceString->length(); i++) {
-                if (replaceString->charAt(i) == '$') {
-                    hasDollar = true;
-                    break;
-                }
-            }
-
-            StringBuilder builder;
-            if (!hasDollar) {
-                // flat replace
-                int32_t matchCount = result.m_matchResults.size();
-                builder.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
-                for (int32_t i = 0; i < matchCount; i++) {
-                    String* res = replaceString;
-                    builder.appendString(res);
-                    if (i < matchCount - 1) {
-                        builder.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
-                    }
-                }
-                builder.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
-            } else {
-                // dollar replace
-                int32_t matchCount = result.m_matchResults.size();
-                builder.appendSubString(string, 0, result.m_matchResults[0][0].m_start);
-                for (int32_t i = 0; i < matchCount; i++) {
-                    for (unsigned j = 0; j < replaceString->length(); j++) {
-                        if (replaceString->charAt(j) == '$' && (j + 1) < replaceString->length()) {
-                            char16_t c = replaceString->charAt(j + 1);
-                            if (c == '$') {
-                                builder.appendChar(replaceString->charAt(j));
-                            } else if (c == '&') {
-                                builder.appendSubString(string, result.m_matchResults[i][0].m_start, result.m_matchResults[i][0].m_end);
-                            } else if (c == '\'') {
-                                builder.appendSubString(string, result.m_matchResults[i][0].m_end, string->length());
-                            } else if (c == '`') {
-                                builder.appendSubString(string, 0, result.m_matchResults[i][0].m_start);
-                            } else if ('0' <= c && c <= '9') {
-                                size_t idx = c - '0';
-                                bool usePeek = false;
-                                if (j + 2 < replaceString->length()) {
-                                    int peek = replaceString->charAt(j + 2) - '0';
-                                    if (0 <= peek && peek <= 9) {
-                                        idx *= 10;
-                                        idx += peek;
-                                        usePeek = true;
-                                    }
-                                }
-
-                                if (idx < result.m_matchResults[i].size() && idx != 0) {
-                                    builder.appendSubString(string, result.m_matchResults[i][idx].m_start, result.m_matchResults[i][idx].m_end);
-                                    if (usePeek)
-                                        j++;
-                                } else {
-                                    idx = c - '0';
-                                    if (idx < result.m_matchResults[i].size() && idx != 0) {
-                                        builder.appendSubString(string, result.m_matchResults[i][idx].m_start, result.m_matchResults[i][idx].m_end);
-                                    } else {
-                                        builder.appendChar('$');
-                                        builder.appendChar(c);
-                                    }
-                                }
-                            } else {
-                                builder.appendChar('$');
-                                builder.appendChar(c);
-                            }
-                            j++;
-                        } else {
-                            builder.appendChar(replaceString->charAt(j));
-                        }
-                    }
-                    if (i < matchCount - 1) {
-                        builder.appendSubString(string, result.m_matchResults[i][0].m_end, result.m_matchResults[i + 1][0].m_start);
-                    }
-                }
-                builder.appendSubString(string, result.m_matchResults[matchCount - 1][0].m_end, string->length());
-            }
-            return builder.finalize(&state);
-        }
-    } else {
-        if (!functionalReplace) {
-            replaceValue = replaceValue.toString(state);
-        }
-        size_t pos = string->find(searchString, 0);
-        String* matched = searchString;
-
-        // If no occurrences of searchString were found, return string.
-        if (pos == SIZE_MAX) {
-            return Value(string);
-        }
-        String* replStr = String::emptyString;
-        if (functionalReplace) {
-            Value parameters[3] = { Value(matched), Value(pos), Value(string) };
-            Value replValue = Object::call(state, replaceValue, Value(), 3, parameters);
-            replStr = replValue.toString(state);
-        } else {
-            StringVector captures;
-            replStr = String::getSubstitution(state, matched, string, pos, captures, Value(), replaceValue.toString(state));
-        }
-        size_t tailpos = pos + matched->length();
-        StringBuilder builder;
-        builder.appendSubString(string, 0, pos);
-        builder.appendSubString(replStr, 0, replStr->length());
-        builder.appendSubString(string, tailpos, string->length());
-        String* newString = builder.finalize(&state);
-        return Value(newString);
-    }
-}
-
-static Value builtinStringReplaceAll(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().object.string(), true, state.context()->staticStrings().replaceAll.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-    Value searchValue = argv[0];
-    Value replaceValue = argv[1];
-    // If searchValue is neither undefined nor null, then
-    if (!searchValue.isUndefinedOrNull()) {
-        // If isRegExp is true, then
-        if (searchValue.isObject() && searchValue.asObject()->isRegExp(state)) {
-            Value flags = searchValue.asObject()->get(state, ObjectPropertyName(state, state.context()->staticStrings().flags)).value(state, searchValue);
-            if (flags.isUndefinedOrNull() || !flags.toString(state)->contains("g")) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().replaceAll.string(), true, state.context()->staticStrings().replaceAll.string(), ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-            }
-        }
-        // Let replacer be ? GetMethod(searchValue, @@replace).
-        Value replacer = Object::getMethod(state, searchValue, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().replace));
-        if (!replacer.isUndefined()) {
-            Value args[2] = { thisValue, replaceValue };
-            // Return ? Call(replacer, searchValue, « O, replaceValue »).
-            return Object::call(state, replacer, searchValue, 2, args);
-        }
-    }
-
-    String* string = thisValue.toString(state);
-    String* searchString = searchValue.toString(state);
-
-    bool functionalReplace = replaceValue.isCallable();
-    // If functionalReplace is false, then
-    if (!functionalReplace) {
-        replaceValue = replaceValue.toString(state);
-    }
-
-    size_t searchLength = searchString->length();
-    size_t advanceBy = (1 < searchLength) ? searchLength : 1;
-
-    std::vector<size_t> matchPositions;
-    // Let position be ! StringIndexOf(string, searchString, 0).
-    size_t position = string->find(searchString, 0);
-    // Repeat, while position is not -1
-    while (position != SIZE_MAX) {
-        matchPositions.push_back(position);
-        position = string->find(searchString, position + advanceBy);
-    }
-    size_t endOfLastMatch = 0;
-
-    StringBuilder builder;
-    String* replacement = String::emptyString;
-    // For each element p of matchPositions, do
-    for (uint i = 0; i < matchPositions.size(); i++) {
-        size_t p = matchPositions[i];
-        builder.appendSubString(string, endOfLastMatch, p);
-        // If functionalReplace is true, then
-        if (functionalReplace) {
-            Value args[3] = { searchString, Value(p), string };
-            replacement = Object::call(state, replaceValue, Value(), 3, args).toString(state);
-        } else {
-            StringVector captures;
-            replacement = String::getSubstitution(state, searchString, string, p, captures, Value(), replaceValue.asString());
-        }
-        builder.appendString(replacement);
-        endOfLastMatch = p + searchLength;
-    }
-    // If endOfLastMatch < the length of string, then
-    if (endOfLastMatch < string->length()) {
-        builder.appendSubString(string, endOfLastMatch, string->length());
-    }
-    return builder.finalize(&state);
-}
-
-static Value builtinStringSearch(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().search.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-
-    Value regexp = argv[0];
-    if (!regexp.isUndefinedOrNull()) {
-        Value searcher = Object::getMethod(state, regexp, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search));
-        if (!searcher.isUndefined()) {
-            Value args[1] = { thisValue };
-            return Object::call(state, searcher, regexp, 1, args);
-        }
-    }
-
-    String* string = thisValue.toString(state);
-    RegExpObject* rx = new RegExpObject(state, regexp.isUndefined() ? String::emptyString : regexp.toString(state), String::emptyString);
-    Value func = rx->get(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().search)).value(state, rx);
-    Value args[1] = { Value(string) };
-    return Object::call(state, func, rx, 1, args);
-}
-
-static Value builtinStringSplit(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, state.context()->staticStrings().split.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-
-    Value separator = argv[0];
-    Value limit = argv[1];
-    bool isSeparatorRegExp = separator.isPointerValue() && separator.asPointerValue()->isRegExpObject();
-
-    // If separator is neither undefined nor null, then
-    if (!separator.isUndefinedOrNull()) {
-        // Let splitter be GetMethod(separator, @@split).
-        Value splitter = Object::getMethod(state, separator, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().split));
-
-        // --- Optmize path
-        // if splitter is builtin RegExp.prototype.split and separator is RegExpObject
-        // we can use old method(ES5) below
-        if (isSeparatorRegExp && splitter.isPointerValue() && splitter.asPointerValue() == state.context()->globalObject()->regexpSplitMethod()) {
-        } else if (!splitter.isUndefined()) {
-            // If splitter is not undefined, then
-            // Return Call(splitter, separator, <<O, limit>>).
-            Value params[2] = { thisValue, limit };
-            return Object::call(state, splitter, separator, 2, params);
-        }
-    }
-
-    // Let S be ? ToString(O).
-    String* S = thisValue.toString(state);
-    // Let A be ! ArrayCreate(0).
-    ArrayObject* A = new ArrayObject(state);
-    // Let lengthA = 0.
-    size_t lengthA = 0;
-    // If limit is undefined, let lim be 2^32 - 1; else let lim be ? ToUint32(limit).
-    uint64_t lim = limit.isUndefined() ? (1ULL << 32) - 1 : limit.toUint32(state);
-    // Let s be the length of S.
-    // Let p = 0.
-    size_t s = S->length(), p = 0;
-
-    PointerValue* P;
-    if (isSeparatorRegExp) {
-        P = separator.asPointerValue()->asRegExpObject();
-    } else {
-        P = separator.toString(state);
-    }
-
-    // If lim = 0, return A.
-    if (lim == 0) {
-        return A;
-    }
-
-    if (separator.isUndefined()) {
-        A->defineOwnProperty(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, ObjectPropertyDescriptor::AllPresent));
-        return A;
-    }
-
-    std::function<Value(String*, int, String*)> splitMatchUsingStr;
-    splitMatchUsingStr = [](String* S, int q, String* R) -> Value {
-        int s = S->length();
-        int r = R->length();
-        if (q + r > s)
-            return Value(false);
-        for (int i = 0; i < r; i++)
-            if (S->charAt(q + i) != R->charAt(i))
-                return Value(false);
-        return Value(q + r);
-    };
-    if (s == 0) {
-        bool ret = true;
-        if (P->isRegExpObject()) {
-            RegexMatchResult result;
-            ret = P->asRegExpObject()->matchNonGlobally(state, S, result, false, 0);
-        } else {
-            Value z = splitMatchUsingStr(S, 0, P->asString());
-            if (z.isBoolean()) {
-                ret = z.asBoolean();
-            }
-        }
-        if (ret)
-            return A;
-        A->defineOwnProperty(state, ObjectPropertyName(state, Value(0)), ObjectPropertyDescriptor(S, ObjectPropertyDescriptor::AllPresent));
-        return A;
-    }
-
-    size_t q = p;
-
-    // 13
-    if (P->isRegExpObject()) {
-        RegExpObject* R = P->asRegExpObject();
-        while (q != s) {
-            RegexMatchResult result;
-            bool ret = R->matchNonGlobally(state, S, result, false, (size_t)q);
-            if (!ret) {
-                break;
-            }
-
-            if ((size_t)result.m_matchResults[0][0].m_end == p) {
-                q++;
-            } else {
-                if (result.m_matchResults[0][0].m_start >= S->length())
-                    break;
-
-                String* T = S->substring(p, result.m_matchResults[0][0].m_start);
-                A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA++)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
-                if (lengthA == lim)
-                    return A;
-                p = result.m_matchResults[0][0].m_end;
-                R->pushBackToRegExpMatchedArray(state, A, lengthA, lim, result, S);
-                if (lengthA == lim)
-                    return A;
-                q = p;
-            }
-        }
-    } else {
-        String* R = P->asString();
-        while (q != s) {
-            Value e = splitMatchUsingStr(S, q, R);
-            if (e == Value(false))
-                q++;
-            else {
-                if ((size_t)e.asInt32() == p)
-                    q++;
-                else {
-                    if (q >= S->length())
-                        break;
-
-                    String* T = S->substring(p, q);
-                    A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA++)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
-                    if (lengthA == lim)
-                        return A;
-                    p = e.asInt32();
-                    q = p;
-                }
-            }
-        }
-    }
-
-    String* T = S->substring(p, s);
-    A->defineOwnProperty(state, ObjectPropertyName(state, Value(lengthA)), ObjectPropertyDescriptor(T, ObjectPropertyDescriptor::AllPresent));
-    return A;
-}
-
-static Value builtinStringCharCodeAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, charCodeAt);
-    int position = argv[0].toInteger(state);
-    Value ret;
-    const auto& data = str->bufferAccessData();
-    if (position < 0 || position >= (int)data.length)
-        ret = Value(std::numeric_limits<double>::quiet_NaN());
-    else {
-        char16_t c;
-        if (data.has8BitContent) {
-            c = ((LChar*)data.buffer)[position];
-        } else {
-            c = ((char16_t*)data.buffer)[position];
-        }
-        ret = Value(c);
-    }
-    return ret;
-}
-
-// https://www.ecma-international.org/ecma-262/6.0/#sec-string.prototype.codepointat
-static Value builtinStringCodePointAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, codePointAt);
-    int position = argv[0].toInteger(state);
-    Value ret;
-    const auto& data = str->bufferAccessData();
-    const int size = (int)data.length;
-    if (position < 0 || position >= size)
-        return Value();
-
-    char16_t first;
-    if (data.has8BitContent) {
-        first = ((LChar*)data.buffer)[position];
-    } else {
-        first = ((char16_t*)data.buffer)[position];
-    }
-
-    if (first < 0xD800 || first > 0xDBFF || (position + 1) == size) {
-        return Value(first);
-    }
-
-    char16_t second;
-    if (data.has8BitContent) {
-        second = ((LChar*)data.buffer)[position + 1];
-    } else {
-        second = ((char16_t*)data.buffer)[position + 1];
-    }
-
-    if (second < 0xDC00 || second > 0xDFFF) {
-        return Value(first);
-    }
-
-    int cp = ((first - 0xD800) * 1024) + (second - 0xDC00) + 0x10000;
-    return Value(cp);
-}
-
-static Value builtinStringCharAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, charAt);
-
-    int64_t position = 0;
-    if (argc > 0) {
-        position = argv[0].toInteger(state);
-    }
-
-    const auto& accessData = str->bufferAccessData();
-
-    if (LIKELY(0 <= position && position < (int64_t)accessData.length)) {
-        char16_t c;
-        if (accessData.has8BitContent) {
-            c = ((LChar*)accessData.buffer)[position];
-        } else {
-            c = ((char16_t*)accessData.buffer)[position];
-        }
-        if (LIKELY(c < ESCARGOT_ASCII_TABLE_MAX)) {
-            return state.context()->staticStrings().asciiTable[c].string();
-        } else {
-            return String::fromCharCode(c);
-        }
-    } else {
-        return String::emptyString;
-    }
-}
-
-static Value builtinStringFromCharCode(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (argc == 1) {
-        char16_t c = argv[0].toUint32(state) & 0xFFFF;
-        if (c < ESCARGOT_ASCII_TABLE_MAX)
-            return state.context()->staticStrings().asciiTable[c].string();
-        return String::fromCharCode(c);
-    }
-
-    StringBuilder builder;
-    for (size_t i = 0; i < argc; i++) {
-        builder.appendChar((char16_t)argv[i].toUint32(state));
-    }
-    return builder.finalize(&state);
-}
-
-static Value builtinStringFromCodePoint(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    StringBuilder builder;
-    for (size_t nextIndex = 0; nextIndex < argc; nextIndex++) {
-        Value next = argv[nextIndex];
-        double nextCP = next.toNumber(state);
-        double toIntegerNexCP = next.toInteger(state);
-
-        if (nextCP != toIntegerNexCP || nextCP < 0 || nextCP > 0x10FFFF) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "invalid code point");
-        }
-
-        uint32_t cp = (uint32_t)nextCP;
-
-        if (cp <= 65535) {
-            builder.appendChar((char16_t)cp);
-        } else {
-            char16_t cu1 = floor((cp - 65536) / 1024) + 0xD800;
-            char16_t cu2 = ((cp - 65536) % 1024) + 0xDC00;
-
-            builder.appendChar(cu1);
-            builder.appendChar(cu2);
-        }
-    }
-
-    return builder.finalize(&state);
-}
-
-static Value builtinStringConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, concat);
-    for (size_t i = 0; i < argc; i++) {
-        String* appendStr = argv[i].toString(state);
-        str = RopeString::createRopeString(str, appendStr, &state);
-    }
-    return Value(str);
-}
-
-static Value builtinStringSlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, slice);
-    size_t len = str->length();
-    double start = argv[0].toInteger(state);
-    double end = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
-    int from = (start < 0) ? std::max(len + start, 0.0) : std::min(start, (double)len);
-    int to = (end < 0) ? std::max(len + end, 0.0) : std::min(end, (double)len);
-    int span = std::max(to - from, 0);
-    return str->substring(from, from + span);
-}
-
-#if defined(ENABLE_ICU)
-static String* stringToLocaleConvertCase(ExecutionState& state, String* str, String* locale, bool isUpper)
-{
-    int32_t len = str->length();
-    char16_t* src = ALLOCA(len * 2, char16_t, state);
-    if (str->has8BitContent()) {
-        const LChar* buf = str->characters8();
-        for (int32_t i = 0; i < len; i++) {
-            src[i] = buf[i];
-        }
-    } else {
-        memcpy(src, str->characters16(), len * 2);
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    int32_t dest_length = len * 3;
-    char16_t* dest = ALLOCA(dest_length * 2, char16_t, state);
-    if (isUpper) {
-        dest_length = u_strToUpper(dest, dest_length, src, len, (const char*)locale->characters8(), &status);
-    } else {
-        dest_length = u_strToLower(dest, dest_length, src, len, (const char*)locale->characters8(), &status);
-    }
-
-    ASSERT(status != U_BUFFER_OVERFLOW_ERROR);
-    ASSERT(U_SUCCESS(status));
-    return new UTF16String(dest, dest_length);
-}
-#endif
-
-static Value builtinStringToLowerCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLowerCase);
-    if (str->has8BitContent()) {
-        Latin1StringData newStr;
-        size_t len = str->length();
-        newStr.resizeWithUninitializedValues(len);
-        const LChar* buf = str->characters8();
-        for (size_t i = 0; i < len; i++) {
-#if defined(ENABLE_ICU)
-            char32_t u2 = u_tolower(buf[i]);
-#else
-            char32_t u2 = tolower(buf[i]);
-#endif
-            ASSERT(u2 < 256);
-            newStr[i] = u2;
-        }
-        return new Latin1String(std::move(newStr));
-    }
-
-#if defined(ENABLE_ICU)
-    return stringToLocaleConvertCase(state, str, String::emptyString, false);
-#else
-    size_t len = str->length();
-    UTF16StringData newStr;
-    if (str->has8BitContent()) {
-        const LChar* buf = str->characters8();
-        newStr.resizeWithUninitializedValues(len);
-        for (size_t i = 0; i < len; i++) {
-            newStr[i] = buf[i];
-        }
-    } else {
-        newStr = UTF16StringData(str->characters16(), len);
-    }
-    char16_t* buf = newStr.data();
-    for (size_t i = 0; i < len;) {
-        char32_t c;
-        size_t iBefore = i;
-        U16_NEXT(buf, i, len, c);
-
-        c = tolower(c);
-        if (c <= 0x10000) {
-            char16_t c2 = (char16_t)c;
-            buf[iBefore] = c2;
-        } else {
-            buf[iBefore] = (char16_t)(0xD800 + ((c - 0x10000) >> 10));
-            buf[iBefore + 1] = (char16_t)(0xDC00 + ((c - 0x10000) & 1023));
-        }
-    }
-    return new UTF16String(std::move(newStr));
-#endif
-}
-
-static Value builtinStringToUpperCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, toUpperCase);
-    if (str->has8BitContent()) {
-        Latin1StringData newStr;
-        size_t len = str->length();
-        newStr.resizeWithUninitializedValues(len);
-
-        bool fitTo8Bit = true;
-        size_t sharpSCount = 0;
-        const LChar* buf = str->characters8();
-        for (size_t i = 0; i < len; i++) {
-            LChar ch = buf[i];
-            // U+00B5 and U+00FF are mapped to a character beyond U+00FF
-            if (UNLIKELY(ch == 0xB5 || ch == 0xFF)) {
-                fitTo8Bit = false;
-                break;
-            }
-            // Lower case sharp-S converts to "SS" (two characters)
-            if (UNLIKELY(ch == 0xDF)) {
-                sharpSCount++;
-                continue;
-            }
-#if defined(ENABLE_ICU)
-            char32_t u2 = u_toupper(ch);
-#else
-            char32_t u2 = toupper(ch);
-#endif
-            ASSERT(u2 < 256);
-            newStr[i] = u2;
-        }
-        if (fitTo8Bit) {
-            if (UNLIKELY(sharpSCount > 0)) {
-                Latin1StringData newStr2;
-                newStr2.resizeWithUninitializedValues(len + sharpSCount);
-                size_t destIndex = 0;
-                for (size_t i = 0; i < len; i++) {
-                    LChar ch = buf[i];
-                    if (ch != 0xDF) {
-                        newStr2[destIndex++] = newStr[i];
-                    } else {
-                        newStr2[destIndex++] = 'S';
-                        newStr2[destIndex++] = 'S';
-                    }
-                }
-                ASSERT(destIndex == len + sharpSCount);
-                return new Latin1String(std::move(newStr2));
-            }
-            return new Latin1String(std::move(newStr));
-        }
-    }
-
-#if defined(ENABLE_ICU)
-    return stringToLocaleConvertCase(state, str, String::emptyString, true);
-#else
-    size_t len = str->length();
-    UTF16StringData newStr;
-    if (str->has8BitContent()) {
-        const LChar* buf = str->characters8();
-        newStr.resizeWithUninitializedValues(len);
-        for (size_t i = 0; i < len; i++) {
-            newStr[i] = buf[i];
-        }
-    } else
-        newStr = UTF16StringData(str->characters16(), len);
-    char16_t* buf = newStr.data();
-    for (size_t i = 0; i < len;) {
-        char32_t c;
-        size_t iBefore = i;
-        U16_NEXT(buf, i, len, c);
-
-        c = toupper(c);
-        if (c <= 0x10000) {
-            char16_t c2 = (char16_t)c;
-            buf[iBefore] = c2;
-        } else {
-            buf[iBefore] = (char16_t)(0xD800 + ((c - 0x10000) >> 10));
-            buf[iBefore + 1] = (char16_t)(0xDC00 + ((c - 0x10000) & 1023));
-        }
-    }
-    return new UTF16String(std::move(newStr));
-#endif
-}
-
-static Value builtinStringToLocaleLowerCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLocaleLowerCase);
-    Value locales = argc > 0 ? argv[0] : Value();
-    String* locale = Intl::getLocaleForStringLocaleConvertCase(state, locales);
-    if (str->has8BitContent() && locale->length() == 0) {
-        return builtinStringToLowerCase(state, thisValue, argc, argv, newTarget);
-    } else {
-        return stringToLocaleConvertCase(state, str, locale, false);
-    }
-#else
-    return builtinStringToLowerCase(state, thisValue, argc, argv, newTarget);
-#endif
-}
-
-static Value builtinStringToLocaleUpperCase(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, toLocaleUpperCase);
-    Value locales = argc > 0 ? argv[0] : Value();
-    String* locale = Intl::getLocaleForStringLocaleConvertCase(state, locales);
-    if (str->has8BitContent() && locale->length() == 0) {
-        return builtinStringToUpperCase(state, thisValue, argc, argv, newTarget);
-    } else {
-        return stringToLocaleConvertCase(state, str, locale, true);
-    }
-#else
-    return builtinStringToUpperCase(state, thisValue, argc, argv, newTarget);
-#endif
-}
-
-static Value builtinStringTrim(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let S be this value.
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, trim);
-    // Return ? TrimString(S, "start+end").
-    return str->trim(String::TrimBoth);
-}
-
-static Value builtinStringTrimStart(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let S be this value.
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, trimStart);
-    // Return ? TrimString(S, "start").
-    return str->trim(String::TrimStart);
-}
-
-static Value builtinStringTrimEnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let S be this value.
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, trimEnd);
-    // Return ? TrimString(S, "end").
-    return str->trim(String::TrimEnd);
-}
-
-static Value builtinStringValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isString()) {
-        return Value(thisValue);
-    } else if (thisValue.isObject() && thisValue.asObject()->isStringObject()) {
-        return Value(thisValue.asPointerValue()->asStringObject()->primitiveValue());
-    }
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotString);
-    RELEASE_ASSERT_NOT_REACHED();
-}
-
-static Value builtinStringStartsWith(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, startsWith);
-    Value searchString = argv[0];
-    // Let isRegExp be ? IsRegExp(searchString).
-    // If isRegExp is true, throw a TypeError exception.
-
-    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with startsWith");
-    }
-    // Let searchStr be ? ToString(searchString).
-    String* searchStr = searchString.toString(state);
-    // Let pos be ? ToInteger(position). (If position is undefined, this step produces the value 0.)
-    double pos = 0;
-    if (argc >= 2) {
-        pos = argv[1].toInteger(state);
-    }
-
-    // Let len be the number of elements in S.
-    double len = S->length();
-    // Let start be min(max(pos, 0), len).
-    double start = std::min(std::max(pos, 0.0), len);
-    // Let searchLength be the number of elements in searchStr.
-    double searchLength = searchStr->length();
-    // If searchLength+start is greater than len, return false.
-    if (searchLength + start > len) {
-        return Value(false);
-    }
-    // If the sequence of elements of S starting at start of length searchLength is the same as the full element sequence of searchStr, return true.
-    // Otherwise, return false.
-    const auto& srcData = S->bufferAccessData();
-    const auto& src2Data = searchStr->bufferAccessData();
-
-    for (size_t i = 0; i < src2Data.length; i++) {
-        if (srcData.charAt(i + start) != src2Data.charAt(i)) {
-            return Value(false);
-        }
-    }
-
-    return Value(true);
-}
-
-static Value builtinStringEndsWith(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, endsWith);
-    Value searchString = argv[0];
-    // Let isRegExp be ? IsRegExp(searchString).
-    // If isRegExp is true, throw a TypeError exception.
-    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with endsWith");
-    }
-    // Let len be the number of elements in S.
-    double len = S->length();
-
-    // Let searchStr be ? ToString(searchString).
-    String* searchStr = searchString.toString(state);
-    // If endPosition is undefined, let pos be len, else let pos be ? ToInteger(endPosition).
-    double pos = 0;
-    if (argc >= 2 && !argv[1].isUndefined()) {
-        pos = argv[1].toInteger(state);
-    } else {
-        pos = len;
-    }
-
-    // Let end be min(max(pos, 0), len).
-    double end = std::min(std::max(pos, 0.0), len);
-    // Let searchLength be the number of elements in searchStr.
-    double searchLength = searchStr->length();
-    // Let start be end - searchLength.
-    double start = end - searchLength;
-    // If start is less than 0, return false.
-    if (start < 0) {
-        return Value(false);
-    }
-    // If the sequence of elements of S starting at start of length searchLength is the same as the full element sequence of searchStr, return true.
-    const auto& srcData = S->bufferAccessData();
-    const auto& src2Data = searchStr->bufferAccessData();
-    for (size_t i = 0; i < searchLength; i++) {
-        if (srcData.charAt(i + start) != src2Data.charAt(i)) {
-            return Value(false);
-        }
-    }
-
-    return Value(true);
-}
-
-// ( template, ...substitutions )
-static Value builtinStringRaw(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value argTemplate = argv[0];
-    // Let substitutions be a List consisting of all of the arguments passed to this function, starting with the second argument. If fewer than two arguments were passed, the List is empty.
-    // Let numberOfSubstitutions be the number of elements in substitutions.
-    size_t numberOfSubstitutions;
-    if (argc < 2) {
-        numberOfSubstitutions = 0;
-    } else {
-        numberOfSubstitutions = argc - 1;
-    }
-
-    // Let cooked be ? ToObject(template).
-    Object* cooked = argTemplate.toObject(state);
-    // Let raw be ? ToObject(? Get(cooked, "raw")).
-    Object* raw = cooked->get(state, ObjectPropertyName(state.context()->staticStrings().raw)).value(state, cooked).toObject(state);
-    // Let literalSegments be ? ToLength(? Get(raw, "length")).
-    double literalSegments = raw->length(state);
-    // If literalSegments ≤ 0, return the empty string.
-    if (literalSegments <= 0) {
-        return String::emptyString;
-    }
-    // Let stringElements be a new empty List.
-    StringBuilder stringElements;
-    // Let nextIndex be 0.
-    size_t nextIndex = 0;
-    // Repeat
-    while (true) {
-        // Let nextKey be ! ToString(nextIndex).
-        // Let nextSeg be ? ToString(? Get(raw, nextKey)).
-        String* nextSeg = raw->get(state, ObjectPropertyName(state, Value(nextIndex))).value(state, raw).toString(state);
-        // Append in order the code unit elements of nextSeg to the end of stringElements.
-        for (size_t i = 0; i < nextSeg->length(); i++) {
-            stringElements.appendChar(nextSeg->charAt(i));
-        }
-        // If nextIndex + 1 = literalSegments, then
-        if (nextIndex + 1 == literalSegments) {
-            // Return the String value whose code units are, in order, the elements in the List stringElements. If stringElements has no elements, the empty string is returned.
-            return stringElements.finalize(&state);
-        }
-        Value next;
-        // If nextIndex < numberOfSubstitutions, let next be substitutions[nextIndex].
-        if (nextIndex < numberOfSubstitutions) {
-            next = argv[nextIndex + 1];
-        } else {
-            // Else, let next be the empty String.
-            next = String::emptyString;
-        }
-        // Let nextSub be ? ToString(next).
-        String* nextSub = next.toString(state);
-        // Append in order the code unit elements of nextSub to the end of stringElements.
-        stringElements.appendString(nextSub);
-        // Let nextIndex be nextIndex + 1.
-        nextIndex++;
-    }
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#sec-string.prototype.padstart
-// 21.1.3.14String.prototype.padStart( maxLength [ , fillString ] )
-static Value builtinStringPadStart(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, padStart);
-
-    // Let intMaxLength be ? ToLength(maxLength).
-    // Let stringLength be the number of elements in S.
-    uint64_t intMaxLength = 0;
-    if (argc >= 1) {
-        intMaxLength = argv[0].toLength(state);
-    }
-    uint64_t stringLength = S->length();
-
-    // If intMaxLength is not greater than stringLength, return S.
-    if (intMaxLength <= stringLength) {
-        return S;
-    }
-
-    // If fillString is undefined, let filler be a String consisting solely of the code unit 0x0020 (SPACE).
-    // Else, let filler be ? ToString(fillString).
-    String* filler;
-    if (argc >= 2 && (!argv[1].isUndefined())) {
-        filler = argv[1].toString(state);
-    } else {
-        filler = state.context()->staticStrings().asciiTable[0x20].string();
-    }
-
-    // If filler is the empty String, return S.
-    if (filler->length() == 0) {
-        return S;
-    }
-
-    // Let fillLen be intMaxLength - stringLength.
-    uint64_t fillLen = intMaxLength - stringLength;
-
-    // Let truncatedStringFiller be a new String value consisting of repeated concatenations of filler truncated to length fillLen.
-    StringBuilder sb;
-    while (sb.contentLength() < fillLen) {
-        sb.appendString(filler);
-    }
-
-    // Build the string, than truncate the characters over fillLen
-    String* truncatedStringFiller = sb.finalize(&state);
-    truncatedStringFiller = truncatedStringFiller->substring(0, fillLen);
-
-    // Return a new String value computed by the concatenation of truncatedStringFiller and S.
-    sb.appendString(truncatedStringFiller);
-    sb.appendString(S);
-    return sb.finalize(&state);
-}
-
-// https://www.ecma-international.org/ecma-262/8.0/#sec-string.prototype.padend
-// 21.1.3.13String.prototype.padEnd( maxLength [ , fillString ] )
-static Value builtinStringPadEnd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, padStart);
-
-    // Let intMaxLength be ? ToLength(maxLength).
-    // Let stringLength be the number of elements in S.
-    uint64_t intMaxLength = 0;
-    if (argc >= 1) {
-        intMaxLength = argv[0].toLength(state);
-    }
-    uint64_t stringLength = S->length();
-
-    // If intMaxLength is not greater than stringLength, return S.
-    if (intMaxLength <= stringLength) {
-        return S;
-    }
-
-    // If fillString is undefined, let filler be a String consisting solely of the code unit 0x0020 (SPACE).
-    // Else, let filler be ? ToString(fillString).
-    String* filler;
-    if (argc >= 2 && (!argv[1].isUndefined())) {
-        filler = argv[1].toString(state);
-    } else {
-        filler = state.context()->staticStrings().asciiTable[0x20].string();
-    }
-
-    // If filler is the empty String, return S.
-    if (filler->length() == 0) {
-        return S;
-    }
-
-    // Let fillLen be intMaxLength - stringLength.
-    uint64_t fillLen = intMaxLength - stringLength;
-
-    // Let truncatedStringFiller be a new String value consisting of repeated concatenations of filler truncated to length fillLen.
-    StringBuilder sb;
-    while (sb.contentLength() < fillLen) {
-        sb.appendString(filler);
-    }
-
-    // Build the string, than truncate the characters over fillLen
-    String* truncatedStringFiller = sb.finalize(&state);
-    truncatedStringFiller = truncatedStringFiller->substring(0, fillLen);
-
-    // Return a new String value computed by the concatenation of S and truncatedStringFiller.
-    sb.appendString(S);
-    sb.appendString(truncatedStringFiller);
-    return sb.finalize(&state);
-}
-
-// http://www.ecma-international.org/ecma-262/6.0/#sec-createhtml
-// Runtime Semantics: CreateHTML ( string, tag, attribute, value )
-static String* createHTML(ExecutionState& state, Value string, String* tag, String* attribute, Value value, AtomicString methodName)
-{
-    // Let str be RequireObjectCoercible(string).
-    // Let S be ToString(str).
-    // ReturnIfAbrupt(S).
-    if (string.isUndefinedOrNull()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().String.string(), true, methodName.string(), ErrorObject::Messages::GlobalObject_ThisUndefinedOrNull);
-    }
-    String* S = string.toString(state);
-
-    // Let p1 be the String value that is the concatenation of "<" and tag.
-    StringBuilder sb;
-    sb.appendChar('<');
-    sb.appendString(tag);
-    String* p1 = sb.finalize(&state);
-    // If attribute is not the empty String, then
-    if (attribute->length()) {
-        // Let V be ToString(value).
-        String* V = value.toString(state);
-        // ReturnIfAbrupt(V).
-        // Let escapedV be the String value that is the same as V except that each occurrence of the code unit 0x0022 (QUOTATION MARK) in V has been replaced with the six code unit sequence "&quot;".
-        StringBuilder sb;
-        for (size_t i = 0; i < V->length(); i++) {
-            char16_t ch = V->charAt(i);
-            if (ch == 0x22) {
-                sb.appendString("&quot;");
-            } else {
-                sb.appendChar(ch);
-            }
-        }
-        String* escapedV = sb.finalize(&state);
-
-        // Let p1 be the String value that is the concatenation of the following String values:
-        // The String value of p1
-        // Code unit 0x0020 (SPACE)
-        // The String value of attribute
-        // Code unit 0x003D (EQUALS SIGN)
-        // Code unit 0x0022 (QUOTATION MARK)
-        // The String value of escapedV
-        // Code unit 0x0022 (QUOTATION MARK)
-        sb.appendString(p1);
-        sb.appendChar((char)0x20);
-        sb.appendString(attribute);
-        sb.appendChar((char)0x3d);
-        sb.appendChar((char)0x22);
-        sb.appendString(escapedV);
-        sb.appendChar((char)0x22);
-        p1 = sb.finalize(&state);
-    }
-    // Let p2 be the String value that is the concatenation of p1 and ">".
-    // Let p3 be the String value that is the concatenation of p2 and S.
-    // Let p4 be the String value that is the concatenation of p3, "</", tag, and ">".
-    // Return p4.
-    sb.appendString(p1);
-    sb.appendChar('>');
-    sb.appendString(S);
-    sb.appendString("</");
-    sb.appendString(tag);
-    sb.appendChar('>');
-    return sb.finalize(&state);
-}
-
-// http://www.ecma-international.org/ecma-262/6.0/#sec-additional-properties-of-the-string.prototype-object
-
-static Value builtinStringSubstr(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, substr);
-    if (argc < 1) {
-        return str;
-    }
-    double intStart = argv[0].toInteger(state);
-    double end;
-    if (argc > 1) {
-        if (argv[1].isUndefined()) {
-            end = std::numeric_limits<double>::infinity();
-        } else
-            end = argv[1].toInteger(state);
-    } else {
-        end = std::numeric_limits<double>::infinity();
-    }
-    double size = str->length();
-    if (intStart < 0)
-        intStart = std::max(size + intStart, 0.0);
-    double resultLength = std::min(std::max(end, 0.0), size - intStart);
-    if (resultLength <= 0)
-        return String::emptyString;
-
-    return str->substring(intStart, intStart + resultLength);
-}
-
-static Value builtinStringAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_STRING(str, String, substr);
-    size_t len = str->length();
-    double relativeStart = argv[0].toInteger(state);
-    if (relativeStart < 0) {
-        relativeStart = len + relativeStart;
-    }
-    if (relativeStart < 0 || relativeStart >= len) {
-        return Value();
-    }
-    return String::fromCharCode(str->charAt(relativeStart));
-}
-
-#define DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fnName, P0, P1, P2)                                                                    \
-    static Value builtinString##fnName(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
-    {                                                                                                                                 \
-        return createHTML(state, thisValue, P0, P1, P2, state.context()->staticStrings().fnName);                                     \
-    }
-
-// String.prototype.anchor (name)
-// Return CreateHTML(S, "a", "name", name).
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(anchor, state.context()->staticStrings().asciiTable[(size_t)'a'].string(), state.context()->staticStrings().name.string(), argv[0])
-// String.prototype.big ()
-// Return CreateHTML(S, "big", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(big, state.context()->staticStrings().big.string(), String::emptyString, String::emptyString)
-// String.prototype.blink ()
-// Return CreateHTML(S, "blink", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(blink, state.context()->staticStrings().blink.string(), String::emptyString, String::emptyString)
-// String.prototype.bold ()
-// Return CreateHTML(S, "b", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(bold, state.context()->staticStrings().asciiTable[(size_t)'b'].string(), String::emptyString, String::emptyString)
-// String.prototype.fixed ()
-// Return CreateHTML(S, "tt", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fixed, String::fromASCII("tt"), String::emptyString, String::emptyString)
-// String.prototype.fontcolor (color)
-// Return CreateHTML(S, "font", "color", color).
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontcolor, String::fromASCII("font"), String::fromASCII("color"), argv[0])
-// String.prototype.fontsize (size)
-// Return CreateHTML(S, "font", "size", size).
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontsize, String::fromASCII("font"), state.context()->staticStrings().size.string(), argv[0])
-// String.prototype.italics ()
-// Return CreateHTML(S, "i", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(italics, state.context()->staticStrings().asciiTable[(size_t)'i'].string(), String::emptyString, String::emptyString)
-// String.prototype.link (url)
-// Return CreateHTML(S, "a", "href", url).
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(link, state.context()->staticStrings().asciiTable[(size_t)'a'].string(), String::fromASCII("href"), argv[0])
-// String.prototype.small ()
-// Return CreateHTML(S, "small", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(small, state.context()->staticStrings().small.string(), String::emptyString, String::emptyString)
-// String.prototype.strike ()
-// Return CreateHTML(S, "strike", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(strike, state.context()->staticStrings().strike.string(), String::emptyString, String::emptyString)
-// String.prototype.sub ()
-// Return CreateHTML(S, "sub", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sub, state.context()->staticStrings().sub.string(), String::emptyString, String::emptyString)
-// String.prototype.sup ()
-// Return CreateHTML(S, "sup", "", "").
-DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sup, state.context()->staticStrings().sup.string(), String::emptyString, String::emptyString)
-
-#undef DEFINE_STRING_ADDITIONAL_HTML_FUNCTION
-
-static Value builtinStringIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, includes);
-    // Let isRegExp be ? IsRegExp(searchString).
-    // If isRegExp is true, throw a TypeError exception.
-    Value searchString = argv[0];
-    if (searchString.isObject() && searchString.asObject()->isRegExp(state)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "can't use RegExp with includes");
-    }
-
-    // Let searchStr be ? ToString(searchString).
-    String* searchStr = searchString.toString(state);
-
-    // Let pos be ? ToInteger(position). (If position is undefined, this step produces the value 0.)
-    double pos = 0;
-    if (argc >= 2) {
-        pos = argv[1].toInteger(state);
-    }
-
-    // Let len be the number of elements in S.
-    double len = S->length();
-
-    // Let start be min(max(pos, 0), len).
-    double start = std::min(std::max(pos, 0.0), len);
-    // Let searchLen be the number of elements in searchStr.
-    // If there exists any integer k not smaller than start such that k + searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the code unit at index k+j of S is the same as the code unit at index j of searchStr, return true; but if there is no such integer k, return false.
-    auto ret = S->find(searchStr, start);
-    if (ret == SIZE_MAX) {
-        return Value(false);
-    }
-    return Value(true);
-}
-
-static Value builtinStringIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isStringIteratorObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().StringIterator.string(), true, state.context()->staticStrings().next.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    StringIteratorObject* iter = thisValue.asObject()->asIteratorObject()->asStringIteratorObject();
-    return iter->next(state);
-}
-
-static Value builtinStringIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? RequireObjectCoercible(this value).
-    // Let S be ? ToString(O).
-    RESOLVE_THIS_BINDING_TO_STRING(S, String, iterator);
-    // Return CreateStringIterator(S).
-    return new StringIteratorObject(state, S);
-}
-
-void GlobalObject::installString(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    m_string = new NativeFunctionObject(state, NativeFunctionInfo(strings->String, builtinStringConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_string->setGlobalIntrinsicObject(state);
-
-    m_stringPrototype = new StringObject(state, m_objectPrototype, String::emptyString);
-    m_stringPrototype->setGlobalIntrinsicObject(state, true);
-    m_string->setFunctionPrototype(state, m_stringPrototype);
-
-    m_stringPrototype->defineOwnProperty(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinStringToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.1.3.4 String.prototype.concat
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->concat),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->concat, builtinStringConcat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.1.3.8 String.prototype.indexOf
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->indexOf),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->indexOf, builtinStringIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->lastIndexOf),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lastIndexOf, builtinStringLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->localeCompare),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->localeCompare, builtinStringLocaleCompare, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.1.3.16 String.prototype.slice
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinStringSlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.1.3.19 String.prototype.substring
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->substring),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->substring, builtinStringSubstring, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->substr),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->substr, builtinStringSubstr, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->match),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->match, builtinStringMatch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->matchAll),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->matchAll, builtinStringMatchAll, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-#if defined(ENABLE_ICU)
-    // The length property of the normalize method is 0.
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->normalize),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->normalize, builtinStringNormalize, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-#endif // ENABLE_ICU
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->repeat),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->repeat, builtinStringRepeat, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->replace),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->replace, builtinStringReplace, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->replaceAll),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->replaceAll, builtinStringReplaceAll, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->search),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->search, builtinStringSearch, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->split),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->split, builtinStringSplit, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->charCodeAt),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->charCodeAt, builtinStringCharCodeAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->codePointAt),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->codePointAt, builtinStringCodePointAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->charAt),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->charAt, builtinStringCharAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLowerCase),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLowerCase, builtinStringToLowerCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toUpperCase),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toUpperCase, builtinStringToUpperCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleLowerCase),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleLowerCase, builtinStringToLocaleLowerCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleUpperCase),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleUpperCase, builtinStringToLocaleUpperCase, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trim),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->trim, builtinStringTrim, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->padStart),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->padStart, builtinStringPadStart, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->padEnd),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->padEnd, builtinStringPadEnd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    FunctionObject* trimStart = new NativeFunctionObject(state, NativeFunctionInfo(strings->trimStart, builtinStringTrimStart, 0, NativeFunctionInfo::Strict));
-    FunctionObject* trimEnd = new NativeFunctionObject(state, NativeFunctionInfo(strings->trimEnd, builtinStringTrimEnd, 0, NativeFunctionInfo::Strict));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimStart),
-                                                        ObjectPropertyDescriptor(trimStart, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimEnd),
-                                                        ObjectPropertyDescriptor(trimEnd, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimRight),
-                                                        ObjectPropertyDescriptor(trimEnd, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->trimLeft),
-                                                        ObjectPropertyDescriptor(trimStart, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // $21.1.3.26 String.prototype.valueOf
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->valueOf),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->valueOf, builtinStringValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // ES6 builtins
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->startsWith),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->startsWith, builtinStringStartsWith, 1, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->endsWith),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->endsWith, builtinStringEndsWith, 1, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->includes),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->includes, builtinStringIncludes, 1, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinStringIterator, 0, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->at),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->at, builtinStringAt, 1, NativeFunctionInfo::Strict)),
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-#define DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fnName, argLength)                                                                                                                                                    \
-    m_stringPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fnName),                                                                                                                  \
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fnName, builtinString##fnName, argLength, NativeFunctionInfo::Strict)), \
-                                                                                 (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // String.prototype.anchor (name)
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(anchor, 1)
-    // String.prototype.big ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(big, 0)
-    // String.prototype.blink ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(blink, 0)
-    // String.prototype.bold ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(bold, 0)
-    // String.prototype.fixed ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fixed, 0)
-    // String.prototype.fontcolor (color)
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontcolor, 1)
-    // String.prototype.fontsize (size)
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(fontsize, 1)
-    // String.prototype.italics ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(italics, 0)
-    // String.prototype.link (url)
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(link, 1)
-    // String.prototype.small ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(small, 0)
-    // String.prototype.strike ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(strike, 0)
-    // String.prototype.sub ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sub, 0)
-    // String.prototype.sup ()
-    DEFINE_STRING_ADDITIONAL_HTML_FUNCTION(sup, 0)
-
-#undef DEFINE_STRING_ADDITIONAL_HTML_FUNCTION
-
-    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fromCharCode),
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fromCharCode, builtinStringFromCharCode, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fromCodePoint),
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fromCodePoint, builtinStringFromCodePoint, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_string->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->raw),
-                                               ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->raw, builtinStringRaw, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_string->setFunctionPrototype(state, m_stringPrototype);
-
-    m_stringIteratorPrototype = new Object(state, m_iteratorPrototype);
-    m_stringIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_stringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().next),
-                                                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().next, builtinStringIteratorNext, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_stringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
-                                                                ObjectPropertyDescriptor(Value(String::fromASCII("String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(strings->String),
-                      ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinSymbol.cpp
deleted file mode 100644 (file)
index 1a555d0..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "SymbolObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinSymbolConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is not undefined, throw a TypeError exception.
-    if (newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "illegal constructor Symbol");
-    }
-    Optional<String*> descString = nullptr;
-    // If description is undefined, let descString be undefined.
-    if (!(argc == 0 || argv[0].isUndefined())) {
-        // Else, let descString be ? ToString(description).
-        descString = argv[0].toString(state);
-    }
-    // Return a new unique Symbol value whose [[Description]] value is descString.
-    return new Symbol(descString);
-}
-
-#define RESOLVE_THIS_BINDING_TO_SYMBOL(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                           \
-    Symbol* NAME = nullptr;                                                                                                                                                                                                                                  \
-    if (thisValue.isObject()) {                                                                                                                                                                                                                              \
-        if (!thisValue.asObject()->isSymbolObject()) {                                                                                                                                                                                                       \
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-        }                                                                                                                                                                                                                                                    \
-        NAME = thisValue.asObject()->asSymbolObject()->primitiveValue();                                                                                                                                                                                     \
-    } else if (thisValue.isSymbol()) {                                                                                                                                                                                                                       \
-        NAME = thisValue.asSymbol();                                                                                                                                                                                                                         \
-    } else {                                                                                                                                                                                                                                                 \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);     \
-    }
-
-static Value builtinSymbolToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, toString);
-    return S->symbolDescriptiveString();
-}
-
-static Value builtinSymbolValueOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, valueOf);
-    return Value(S);
-}
-
-static Value builtinSymbolToPrimitive(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_SYMBOL(S, Symbol, toPrimitive);
-    return Value(S);
-}
-
-static Value builtinSymbolFor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let stringKey be ? ToString(key).
-    String* stringKey = argv[0].toString(state);
-    return Symbol::fromGlobalSymbolRegistry(state.context()->vmInstance(), stringKey);
-}
-
-static Value builtinSymbolKeyFor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If Type(sym) is not Symbol, throw a TypeError exception.
-    if (!argv[0].isSymbol()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_IllegalFirstArgument);
-    }
-    Symbol* sym = argv[0].asSymbol();
-    // For each element e of the GlobalSymbolRegistry List (see 19.4.2.1),
-    auto& list = state.context()->vmInstance()->globalSymbolRegistry();
-    for (size_t i = 0; i < list.size(); i++) {
-        // If SameValue(e.[[Symbol]], sym) is true, return e.[[Key]].
-        if (list[i].symbol == sym) {
-            return list[i].key.value();
-        }
-    }
-    // Assert: GlobalSymbolRegistry does not currently contain an entry for sym.
-    // Return undefined.
-    return Value();
-}
-
-static Value builtinSymbolDescriptionGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (thisValue.isSymbol()) {
-        if (!thisValue.asSymbol()->description().hasValue()) {
-            return Value();
-        }
-
-        return thisValue.asSymbol()->description().value();
-
-    } else if (thisValue.isObject() && thisValue.asObject()->isSymbolObject()) {
-        if (!thisValue.asObject()->asSymbolObject()->primitiveValue()->description().hasValue()) {
-            return Value();
-        }
-
-        return thisValue.asObject()->asSymbolObject()->primitiveValue()->description().value();
-
-    } else {
-        ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, "getter called on non-Symbol object");
-    }
-    return Value();
-}
-
-void GlobalObject::installSymbol(ExecutionState& state)
-{
-    m_symbol = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Symbol, builtinSymbolConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_symbol->setGlobalIntrinsicObject(state);
-
-    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringFor),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringFor, builtinSymbolFor, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keyFor),
-                                ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().keyFor, builtinSymbolKeyFor, 1, NativeFunctionInfo::Strict)),
-                                                         (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbolPrototype = new Object(state);
-    m_symbolPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinSymbolToString, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
-                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinSymbolValueOf, 0, NativeFunctionInfo::Strict)),
-                                                                  (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbolPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toPrimitive)),
-                                                        ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.toPrimitive]")), builtinSymbolToPrimitive, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_symbolPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                        ObjectPropertyDescriptor(state.context()->staticStrings().Symbol.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    {
-        Value getter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getDescription, builtinSymbolDescriptionGetter, 0, NativeFunctionInfo::Strict));
-        JSGetterSetter gs(getter, Value());
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        m_symbolPrototype->defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().description), desc);
-    }
-
-
-#define DECLARE_GLOBAL_SYMBOLS(name) \
-    m_symbol->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().name), ObjectPropertyDescriptor(Value(state.context()->vmInstance()->globalSymbols().name), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
-    DEFINE_GLOBAL_SYMBOLS(DECLARE_GLOBAL_SYMBOLS);
-
-    m_symbol->setFunctionPrototype(state, m_symbolPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Symbol),
-                      ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinTypedArray.cpp
deleted file mode 100644 (file)
index ff778c2..0000000
+++ /dev/null
@@ -1,1746 +0,0 @@
-/*
- * Copyright (c) 2017-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "Object.h"
-#include "TypedArrayObject.h"
-#include "IteratorObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-#define RESOLVE_THIS_BINDING_TO_TYPEDARRAY(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                   \
-    if (UNLIKELY(!thisValue.isObject() || !thisValue.asObject()->isTypedArrayObject())) {                                                                                                                                                                \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                    \
-    TypedArrayObject* NAME = thisValue.asPointerValue()->asTypedArrayObject();
-
-
-// https://www.ecma-international.org/ecma-262/10.0/#typedarray-create
-static Object* createTypedArray(ExecutionState& state, const Value& constructor, size_t argc, Value* argv)
-{
-    Object* newTypedArray = Object::construct(state, constructor, argc, argv).toObject(state);
-    TypedArrayObject::validateTypedArray(state, newTypedArray);
-
-    if (argc == 1 && argv[0].isNumber()) {
-        double arrayLength = newTypedArray->asTypedArrayObject()->arrayLength();
-        if (arrayLength < argv[0].asNumber()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "invalid TypedArray length");
-        }
-    }
-
-    return newTypedArray;
-}
-
-static Value getDefaultTypedArrayConstructor(ExecutionState& state, const TypedArrayType type)
-{
-    GlobalObject* glob = state.context()->globalObject();
-    switch (type) {
-    case TypedArrayType::Int8:
-        return glob->int8Array();
-    case TypedArrayType::Uint8:
-        return glob->uint8Array();
-    case TypedArrayType::Uint8Clamped:
-        return glob->uint8ClampedArray();
-    case TypedArrayType::Int16:
-        return glob->int16Array();
-    case TypedArrayType::Uint16:
-        return glob->uint16Array();
-    case TypedArrayType::Int32:
-        return glob->int32Array();
-    case TypedArrayType::Uint32:
-        return glob->uint32Array();
-    case TypedArrayType::Float32:
-        return glob->float32Array();
-    case TypedArrayType::Float64:
-        return glob->float64Array();
-    case TypedArrayType::BigInt64:
-        return glob->bigInt64Array();
-    case TypedArrayType::BigUint64:
-        return glob->bigUint64Array();
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-    return Value();
-}
-
-static Value TypedArraySpeciesCreate(ExecutionState& state, TypedArrayObject* exemplar, size_t argc, Value* argumentList)
-{
-    // Let defaultConstructor be the intrinsic object listed in column one of Table 49 for the value of O’s [[TypedArrayName]] internal slot.
-    Value defaultConstructor = getDefaultTypedArrayConstructor(state, exemplar->typedArrayType());
-    // Let C be SpeciesConstructor(O, defaultConstructor).
-    Value C = exemplar->speciesConstructor(state, defaultConstructor);
-    Value A = Object::construct(state, C, argc, argumentList);
-    TypedArrayObject::validateTypedArray(state, A);
-    if (argc == 1 && argumentList[0].isNumber() && A.asObject()->asTypedArrayObject()->arrayLength() < argumentList->toNumber(state)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayLength);
-    }
-    return A;
-}
-
-static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::Not_Constructor);
-    return Value();
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.from
-static Value builtinTypedArrayFrom(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value C = thisValue;
-    Value source = argv[0];
-
-    if (!C.isConstructor()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
-    }
-
-    Value mapfn;
-    if (argc > 1) {
-        mapfn = argv[1];
-    }
-    Value T;
-    if (argc > 2) {
-        T = argv[2];
-    }
-
-    bool mapping = false;
-    if (!mapfn.isUndefined()) {
-        if (!mapfn.isCallable()) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "mapfn is not callable");
-        }
-        mapping = true;
-    }
-
-    Value usingIterator = Object::getMethod(state, source, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
-    if (!usingIterator.isUndefined()) {
-        ValueVectorWithInlineStorage values = IteratorObject::iterableToList(state, source, usingIterator);
-        size_t len = values.size();
-        Value arg[1] = { Value(len) };
-        Object* targetObj = createTypedArray(state, C, 1, arg);
-
-        size_t k = 0;
-        while (k < len) {
-            Value mappedValue = values[k];
-            if (mapping) {
-                Value args[2] = { values[k], Value(k) };
-                mappedValue = Object::call(state, mapfn, T, 2, args);
-            }
-            targetObj->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
-            k++;
-        }
-
-        return targetObj;
-    }
-
-    Object* arrayLike = source.toObject(state);
-    size_t len = arrayLike->length(state);
-
-    Value arg[1] = { Value(len) };
-    Object* targetObj = createTypedArray(state, C, 1, arg);
-
-    size_t k = 0;
-    while (k < len) {
-        Value kValue = arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike);
-        Value mappedValue = kValue;
-        if (mapping) {
-            // Let mappedValue be Call(mapfn, T, «kValue, k»).
-            Value args[2] = { kValue, Value(k) };
-            mappedValue = Object::call(state, mapfn, T, 2, args);
-        }
-        // Let setStatus be Set(targetObj, Pk, mappedValue, true).
-        targetObj->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
-        k++;
-    }
-
-    return targetObj;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.of
-static Value builtinTypedArrayOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    size_t len = argc;
-    Value C = thisValue;
-    if (!C.isConstructor()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotConstructor);
-    }
-
-    Value arg[1] = { Value(len) };
-    Object* newObj = createTypedArray(state, C, 1, arg);
-
-    size_t k = 0;
-    while (k < len) {
-        Value kValue = argv[k];
-        newObj->setIndexedPropertyThrowsException(state, Value(k), kValue);
-        k++;
-    }
-    return newObj;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.buffer
-static Value builtinTypedArrayBufferGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getBuffer);
-    return buffer->buffer();
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.bytelength
-static Value builtinTypedArrayByteLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteLength);
-    if (buffer->buffer()->isDetachedBuffer()) {
-        return Value(0);
-    }
-    return Value(buffer->byteLength());
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.byteoffset
-static Value builtinTypedArrayByteOffsetGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteOffset);
-    if (buffer->buffer()->isDetachedBuffer()) {
-        return Value(0);
-    }
-    return Value(buffer->byteOffset());
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype.length
-static Value builtinTypedArrayLengthGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(buffer, TypedArray, getbyteOffset);
-    if (buffer->buffer()->isDetachedBuffer()) {
-        return Value(0);
-    }
-    return Value(buffer->arrayLength());
-}
-
-static void initializeTypedArrayFromTypedArray(ExecutionState& state, TypedArrayObject* obj, TypedArrayObject* srcArray)
-{
-    ArrayBufferObject* srcData = srcArray->buffer();
-    srcData->throwTypeErrorIfDetached(state);
-
-    size_t elementLength = srcArray->arrayLength();
-    size_t srcElementSize = srcArray->elementSize();
-    size_t srcByteOffset = srcArray->byteOffset();
-    size_t elementSize = obj->elementSize();
-    uint64_t byteLength = elementSize * elementLength;
-
-    Value bufferConstructor;
-#if defined(ENABLE_THREADING)
-    if (srcData->isSharedArrayBufferObject())
-        // Let bufferConstructor be %ArrayBuffer%.
-        bufferConstructor = state.context()->globalObject()->arrayBuffer();
-    else
-#endif
-        // Let bufferConstructor be ? SpeciesConstructor(srcData, %ArrayBuffer%).
-        bufferConstructor = srcData->speciesConstructor(state, state.context()->globalObject()->arrayBuffer());
-
-    ArrayBufferObject* data = nullptr;
-    if (obj->typedArrayType() == srcArray->typedArrayType()) {
-        // Let data be ? CloneArrayBuffer(srcData, srcByteOffset, byteLength, bufferConstructor).
-        data = ArrayBufferObject::cloneArrayBuffer(state, srcData, srcByteOffset, byteLength, bufferConstructor.asObject());
-    } else {
-        // Let data be AllocateArrayBuffer(bufferConstructor, byteLength).
-        data = ArrayBufferObject::allocateArrayBuffer(state, bufferConstructor.asObject(), byteLength);
-        // If IsDetachedBuffer(srcData) is true, throw a TypeError exception.
-        srcData->throwTypeErrorIfDetached(state);
-
-        // Let srcByteIndex be srcByteOffset.
-        size_t srcByteIndex = srcByteOffset;
-        // Let targetByteIndex be 0.
-        size_t targetByteIndex = 0;
-        // Let count be elementLength.
-        size_t count = elementLength;
-        // Repeat, while count > 0
-        while (count > 0) {
-            // Let value be GetValueFromBuffer(srcData, srcByteIndex, srcType).
-            Value value = srcData->getValueFromBuffer(state, srcByteIndex, srcArray->typedArrayType());
-            // Perform SetValueInBuffer(data, targetByteIndex, elementType, value).
-            data->setValueInBuffer(state, targetByteIndex, obj->typedArrayType(), value);
-            // Set srcByteIndex to srcByteIndex + srcElementSize.
-            srcByteIndex += srcElementSize;
-            // Set targetByteIndex to targetByteIndex + elementSize.
-            targetByteIndex += elementSize;
-            // Decrement count by 1.
-            count--;
-        }
-    }
-    // Set O’s [[ViewedArrayBuffer]] internal slot to data.
-    // Set O’s [[ByteLength]] internal slot to byteLength.
-    // Set O’s [[ByteOffset]] internal slot to 0.
-    // Set O’s [[ArrayLength]] internal slot to elementLength.
-    obj->setBuffer(data, 0, byteLength, elementLength);
-}
-
-static void initializeTypedArrayFromArrayBuffer(ExecutionState& state, TypedArrayObject* obj, ArrayBufferObject* buffer, const Value& byteOffset, const Value& length)
-{
-    size_t elementSize = obj->elementSize();
-    uint64_t offset = byteOffset.toIndex(state);
-    if (offset == Value::InvalidIndexValue || offset % elementSize != 0) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-    }
-
-    uint64_t newLength = 0;
-    if (!length.isUndefined()) {
-        newLength = length.toIndex(state);
-        if (newLength == Value::InvalidIndexValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-        }
-    }
-
-    buffer->throwTypeErrorIfDetached(state);
-    size_t bufferByteLength = buffer->byteLength();
-
-    size_t newByteLength = 0;
-    if (length.isUndefined()) {
-        if ((bufferByteLength % elementSize != 0) || (bufferByteLength < offset)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-        }
-        newByteLength = bufferByteLength - offset;
-    } else {
-        newByteLength = newLength * elementSize;
-        if (offset + newByteLength > bufferByteLength) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferOffset);
-        }
-    }
-
-    obj->setBuffer(buffer, offset, newByteLength, newByteLength / elementSize);
-}
-
-static void initializeTypedArrayFromList(ExecutionState& state, TypedArrayObject* obj, const ValueVectorWithInlineStorage& values)
-{
-    size_t len = values.size();
-
-    // Perform ? AllocateTypedArrayBuffer(O, len).
-    size_t elementSize = obj->elementSize();
-    uint64_t byteLength = len * elementSize;
-    ArrayBufferObject* buffer = ArrayBufferObject::allocateArrayBuffer(state, state.context()->globalObject()->arrayBuffer(), byteLength);
-    obj->setBuffer(buffer, 0, byteLength, len);
-
-    size_t k = 0;
-    while (k < len) {
-        // Perform ? Set(O, Pk, kValue, true).
-        obj->setIndexedPropertyThrowsException(state, Value(k), values[k]);
-        k++;
-    }
-}
-
-static void initializeTypedArrayFromArrayLike(ExecutionState& state, TypedArrayObject* obj, Object* arrayLike)
-{
-    size_t len = arrayLike->length(state);
-
-    // Perform ? AllocateTypedArrayBuffer(O, len).
-    size_t elementSize = obj->elementSize();
-    uint64_t byteLength = len * elementSize;
-    ArrayBufferObject* buffer = ArrayBufferObject::allocateArrayBuffer(state, state.context()->globalObject()->arrayBuffer(), byteLength);
-    obj->setBuffer(buffer, 0, byteLength, len);
-
-    size_t k = 0;
-    while (k < len) {
-        // Perform ? Set(O, Pk, kValue, true).
-        obj->setIndexedPropertyThrowsException(state, Value(k), arrayLike->getIndexedProperty(state, Value(k)).value(state, arrayLike));
-        k++;
-    }
-}
-
-template <typename TA>
-static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // if NewTarget is undefined, throw a TypeError
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    if (argc == 0) {
-        // $22.2.4.1 TypedArray ()
-        return TA::allocateTypedArray(state, newTarget.value(), 0);
-    }
-
-    const Value& firstArg = argv[0];
-    if (!firstArg.isObject()) {
-        uint64_t elemlen = firstArg.toIndex(state);
-        if (elemlen == Value::InvalidIndexValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
-        }
-        return TA::allocateTypedArray(state, newTarget.value(), elemlen);
-    }
-
-    ASSERT(firstArg.isObject());
-    Object* argObj = firstArg.asObject();
-    TypedArrayObject* obj = TA::allocateTypedArray(state, newTarget.value());
-
-    if (argObj->isTypedArrayObject()) {
-        initializeTypedArrayFromTypedArray(state, obj, argObj->asTypedArrayObject());
-    } else if (argObj->isArrayBufferObject()) {
-        Value byteOffset = (argc > 1) ? argv[1] : Value();
-        Value length = (argc > 2) ? argv[2] : Value();
-        initializeTypedArrayFromArrayBuffer(state, obj, argObj->asArrayBufferObject(), byteOffset, length);
-    } else {
-        Value usingIterator = Object::getMethod(state, argObj, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator));
-        if (!usingIterator.isUndefined()) {
-            ValueVectorWithInlineStorage values = IteratorObject::iterableToList(state, argObj, usingIterator);
-            initializeTypedArrayFromList(state, obj, values);
-        } else {
-            initializeTypedArrayFromArrayLike(state, obj, argObj);
-        }
-    }
-
-    return obj;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.copywithin
-static Value builtinTypedArrayCopyWithin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
-
-    // Let len be O.[[ArrayLength]].
-    double len = O->arrayLength();
-
-    // Let relativeTarget be ToInteger(target).
-    double relativeTarget = argv[0].toInteger(state);
-    // If relativeTarget < 0, let to be max((len + relativeTarget),0); else let to be min(relativeTarget, len).
-    double to = (relativeTarget < 0.0) ? std::max((len + relativeTarget), 0.0) : std::min(relativeTarget, len);
-
-    // Let relativeStart be ToInteger(start).
-    double relativeStart = argv[1].toInteger(state);
-    // If relativeStart < 0, let from be max((len + relativeStart),0); else let from be min(relativeStart, len).
-    double from = (relativeStart < 0.0) ? std::max((len + relativeStart), 0.0) : std::min(relativeStart, len);
-
-    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
-    double relativeEnd = (argc <= 2 || argv[2].isUndefined()) ? len : argv[2].toInteger(state);
-    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
-    double finalEnd = (relativeEnd < 0.0) ? std::max((len + relativeEnd), 0.0) : std::min(relativeEnd, len);
-
-    // Let count be min(final-from, len-to).
-    double count = std::min(finalEnd - from, len - to);
-    // If count > 0, then
-    if (count > 0) {
-        // Let buffer be O.[[ViewedArrayBuffer]].
-        ArrayBufferObject* buffer = O->buffer();
-        // If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
-        buffer->throwTypeErrorIfDetached(state);
-        // Let typedArrayName be the String value of O.[[TypedArrayName]].
-        // Let elementSize be the Number value of the Element Size value specified in Table 59 for typedArrayName.
-        size_t elementSize = O->elementSize();
-        // Let byteOffset be O.[[ByteOffset]].
-        size_t byteOffset = O->byteOffset();
-        // Let toByteIndex be to × elementSize + byteOffset.
-        size_t toByteIndex = to * elementSize + byteOffset;
-        // Let fromByteIndex be from × elementSize + byteOffset.
-        size_t fromByteIndex = from * elementSize + byteOffset;
-        // Let countBytes be count × elementSize.
-        size_t countBytes = count * elementSize;
-
-        int8_t direction = 0;
-        // If fromByteIndex < toByteIndex and toByteIndex < fromByteIndex + countBytes, then
-        if (fromByteIndex < toByteIndex && toByteIndex < fromByteIndex + countBytes) {
-            // Let direction be -1.
-            direction = -1;
-            // Set fromByteIndex to fromByteIndex + countBytes - 1.
-            fromByteIndex = fromByteIndex + countBytes - 1;
-            // Set toByteIndex to toByteIndex + countBytes - 1.
-            toByteIndex = toByteIndex + countBytes - 1;
-        } else {
-            // Let direction be 1.
-            direction = 1;
-        }
-
-        // Repeat, while countBytes > 0
-        while (countBytes > 0) {
-            // Let value be GetValueFromBuffer(buffer, fromByteIndex, "Uint8", true, "Unordered").
-            Value value = buffer->getValueFromBuffer(state, fromByteIndex, TypedArrayType::Uint8);
-            // Perform SetValueInBuffer(buffer, toByteIndex, "Uint8", value, true, "Unordered").
-            buffer->setValueInBuffer(state, toByteIndex, TypedArrayType::Uint8, value);
-            // Set fromByteIndex to fromByteIndex + direction.
-            fromByteIndex += direction;
-            // Set toByteIndex to toByteIndex + direction.
-            toByteIndex += direction;
-            // Decrease countBytes by 1.
-            countBytes--;
-        }
-    }
-
-    // return O.
-    return O;
-}
-
-static Value builtinTypedArrayIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // NOTE: Same algorithm as Array.prototype.indexOf
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, indexOf);
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Let lenValue be this object's [[ArrayLength]] internal slot.
-    // Let len be ToUint32(lenValue).
-    size_t len = O->asTypedArrayObject()->arrayLength();
-
-    // If len is 0, return -1.
-    if (len == 0) {
-        return Value(-1);
-    }
-
-    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be 0.
-    double n = 0;
-    if (argc > 1) {
-        n = argv[1].toInteger(state);
-    }
-
-    // If n ≥ len, return -1.
-    if (n >= len) {
-        return Value(-1);
-    }
-
-    double doubleK;
-    // If n ≥ 0, then
-    if (n >= 0) {
-        // Let k be n.
-        doubleK = (n == -0) ? 0 : n;
-    } else {
-        // Else, n<0
-        // Let k be len + n
-        doubleK = len + n;
-        // If k is less than 0, then let k be 0.
-        if (doubleK < 0) {
-            doubleK = 0;
-        }
-    }
-    size_t k = (size_t)doubleK;
-
-    // Repeat, while k<len
-    while (k < len) {
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
-        ObjectGetResult kPresent = O->getIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent.hasValue()) {
-            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
-            Value elementK = kPresent.value(state, O);
-
-            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
-            if (elementK.equalsTo(state, argv[0])) {
-                // If same is true, return k.
-                return Value(k);
-            }
-        }
-        // Increase k by 1.
-        k++;
-    }
-
-    // Return -1.
-    return Value(-1);
-}
-
-static Value builtinTypedArrayLastIndexOf(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // NOTE: Same algorithm as Array.prototype.lastIndexOf
-    // Let O be the result of calling ToObject passing the this value as the argument.
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, lastIndexOf);
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Let lenValue be this object's [[ArrayLength]] internal slot.
-    // Let len be ToUint32(lenValue).
-    size_t len = O->asTypedArrayObject()->arrayLength();
-
-    // If len is 0, return -1.
-    if (len == 0) {
-        return Value(-1);
-    }
-
-    // If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
-    double n;
-    if (argc > 1) {
-        n = argv[1].toInteger(state);
-    } else {
-        n = len - 1;
-    }
-
-    // If n ≥ 0, then let k be min(n, len – 1).
-    double doubleK;
-    if (n >= 0) {
-        doubleK = (n == -0) ? 0 : std::min(n, len - 1.0);
-    } else {
-        // Else, n < 0
-        // Let k be len + n.
-        doubleK = len + n;
-    }
-
-    if (doubleK < 0) {
-        return Value(-1);
-    }
-    int64_t k = (int64_t)doubleK;
-
-    // Repeat, while k≥ 0
-    while (k >= 0) {
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument ToString(k).
-        ObjectGetResult kPresent = O->getIndexedProperty(state, Value(k));
-        // If kPresent is true, then
-        if (kPresent.hasValue()) {
-            // Let elementK be the result of calling the [[Get]] internal method of O with the argument ToString(k).
-            Value elementK = kPresent.value(state, O);
-
-            // Let same be the result of applying the Strict Equality Comparison Algorithm to searchElement and elementK.
-            if (elementK.equalsTo(state, argv[0])) {
-                // If same is true, return k.
-                return Value(k);
-            }
-        } else {
-            int64_t result;
-            Object::nextIndexBackward(state, O, k, -1, result);
-            k = result;
-            continue;
-        }
-        // Decrease k by 1.
-        k--;
-    }
-
-    // Return -1.
-    return Value(-1);
-}
-
-static Value builtinTypedArrayIncludes(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ? ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, includes);
-    TypedArrayObject::validateTypedArray(state, O);
-
-    size_t len = O->asTypedArrayObject()->arrayLength();
-
-    // If len is 0, return false.
-    if (len == 0) {
-        return Value(false);
-    }
-
-    Value searchElement = argv[0];
-    // Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
-    double n = argc >= 2 ? argv[1].toInteger(state) : 0;
-    if (n >= len) {
-        return Value(false);
-    }
-
-    double doubleK;
-    // If n ≥ 0, then
-    if (n >= 0) {
-        // Let k be n.
-        doubleK = n;
-    } else {
-        // Else n < 0,
-        // Let k be len + n.
-        doubleK = len + n;
-        // If k < 0, let k be 0.
-        if (doubleK < 0) {
-            doubleK = 0;
-        }
-    }
-    size_t k = (size_t)doubleK;
-
-    // Repeat, while k < len
-    while (k < len) {
-        // Let elementK be the result of ? Get(O, ! ToString(k)).
-        Value elementK = O->getIndexedProperty(state, Value(k)).value(state, O);
-        // If SameValueZero(searchElement, elementK) is true, return true.
-        if (elementK.equalsToByTheSameValueZeroAlgorithm(state, searchElement)) {
-            return Value(true);
-        }
-        // Increase k by 1.
-        k++;
-    }
-
-    // Return false.
-    return Value(false);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.set-overloaded-offset
-static Value builtinTypedArraySet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    if (!thisValue.isObject() || !thisValue.asObject()->isTypedArrayObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_ThisNotTypedArrayObject);
-    }
-
-    TypedArrayObject* target = thisValue.asObject()->asTypedArrayObject();
-
-    double targetOffset = 0;
-    if (argc > 1) {
-        targetOffset = argv[1].toInteger(state);
-    }
-    if (targetOffset < 0) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), "Start offset is negative");
-    }
-
-    auto typedArrayType = target->typedArrayType();
-    bool isBigIntArray = typedArrayType == TypedArrayType::BigInt64 || typedArrayType == TypedArrayType::BigUint64;
-
-    ArrayBufferObject* targetBuffer = target->buffer();
-    targetBuffer->throwTypeErrorIfDetached(state);
-    size_t targetLength = target->arrayLength();
-    size_t targetElementSize = target->elementSize();
-    size_t targetByteOffset = target->byteOffset();
-
-    Object* src = argv[0].toObject(state);
-    if (!src->isTypedArrayObject()) {
-        // 22.2.3.23.1%TypedArray%.prototype.set ( array [ , offset ] )
-        size_t srcLength = src->length(state);
-        if (srcLength + targetOffset > targetLength) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_InvalidArrayLength);
-        }
-
-        size_t targetByteIndex = targetOffset * targetElementSize + targetByteOffset;
-        size_t k = 0;
-        size_t limit = targetByteIndex + targetElementSize * srcLength;
-        while (targetByteIndex < limit) {
-            Value value = src->get(state, ObjectPropertyName(state, Value(k))).value(state, src);
-            if (UNLIKELY(isBigIntArray)) {
-                value = value.toBigInt(state);
-            } else {
-                value = Value(value.toNumber(state));
-            }
-            targetBuffer->throwTypeErrorIfDetached(state);
-
-            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, "Unordered").
-            targetBuffer->setValueInBuffer(state, targetByteIndex, target->typedArrayType(), value);
-
-            k++;
-            targetByteIndex += targetElementSize;
-        }
-
-        return Value();
-    }
-
-    // 22.2.3.23.2%TypedArray%.prototype.set ( typedArray [ , offset ] )
-    ASSERT(src->isTypedArrayObject());
-    TypedArrayObject* srcTypedArray = src->asTypedArrayObject();
-    ArrayBufferObject* srcBuffer = srcTypedArray->buffer();
-    srcBuffer->throwTypeErrorIfDetached(state);
-
-    size_t srcElementSize = srcTypedArray->elementSize();
-    size_t srcLength = srcTypedArray->arrayLength();
-    size_t srcByteOffset = srcTypedArray->byteOffset();
-
-    if (srcLength + targetOffset > targetLength) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, strings->TypedArray.string(), true, strings->set.string(), ErrorObject::Messages::GlobalObject_InvalidArrayLength);
-    }
-
-    // If one of srcType and targetType contains the substring "Big" and the other does not, throw a TypeError exception.
-    auto srcTypedArrayType = srcTypedArray->typedArrayType();
-    bool isSrcBigIntArray = srcTypedArrayType == TypedArrayType::BigInt64 || srcTypedArrayType == TypedArrayType::BigUint64;
-    if (isBigIntArray != isSrcBigIntArray) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->TypedArray.string(), true, strings->set.string(), "Cannot mix BigIntArray with other Array");
-    }
-
-    size_t srcByteIndex = srcByteOffset;
-    if (srcBuffer == targetBuffer) {
-        size_t srcByteLength = srcTypedArray->byteLength();
-        srcBuffer = ArrayBufferObject::cloneArrayBuffer(state, targetBuffer, srcByteOffset, srcByteLength, state.context()->globalObject()->arrayBuffer());
-        srcByteIndex = 0;
-    }
-
-    size_t targetByteIndex = targetOffset * targetElementSize + targetByteOffset;
-    size_t limit = targetByteIndex + targetElementSize * srcLength;
-
-    if (srcTypedArray->typedArrayType() == target->typedArrayType()) {
-        while (targetByteIndex < limit) {
-            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8", true, "Unordered").
-            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, TypedArrayType::Uint8);
-            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, "Uint8", value, true, "Unordered").
-            targetBuffer->setValueInBuffer(state, targetByteIndex, TypedArrayType::Uint8, value);
-            srcByteIndex++;
-            targetByteIndex++;
-        }
-    } else {
-        while (targetByteIndex < limit) {
-            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, "Unordered").
-            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, srcTypedArray->typedArrayType());
-            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, "Unordered").
-            targetBuffer->setValueInBuffer(state, targetByteIndex, target->typedArrayType(), value);
-            srcByteIndex += srcElementSize;
-            targetByteIndex += targetElementSize;
-        }
-    }
-
-    return Value();
-}
-
-static Value builtinTypedArraySome(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, some);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.some as defined in 22.1.3.23 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
-                                       state.context()->staticStrings().some.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    Value T;
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let k be 0.
-    size_t k = 0;
-
-    // Repeat, while k < len
-    while (k < len) {
-        ObjectGetResult kResult = O->getIndexedProperty(state, Value(k));
-        // Let kValue be the result of calling the [[Get]] internal method of O with argument ToString(k).
-        Value kValue = kResult.value(state, O);
-        // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-        Value args[] = { kValue, Value(k), O };
-        Value testResult = Object::call(state, callbackfn, T, 3, args);
-
-        // If ToBoolean(testResult) is true, return true.
-        if (testResult.toBoolean(state)) {
-            return Value(true);
-        }
-
-        // Increase k by 1.
-        k++;
-    }
-    // Return false.
-    return Value(false);
-}
-
-static Value builtinTypedArraySort(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, sort);
-    // Let buffer be TypedArrayObject::validateTypedArray(obj).
-    ArrayBufferObject* buffer = TypedArrayObject::validateTypedArray(state, O);
-
-    // Let len be the value of O’s [[ArrayLength]] internal slot.
-    int64_t len = O->asTypedArrayObject()->arrayLength();
-
-    Value cmpfn = argv[0];
-    if (!cmpfn.isUndefined() && !cmpfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().sort.string(), ErrorObject::Messages::GlobalObject_FirstArgumentNotCallable);
-    }
-    bool defaultSort = (argc == 0) || cmpfn.isUndefined();
-
-    // [defaultSort, &cmpfn, &state, &buffer]
-    O->sort(state, len, [&](const Value& x, const Value& y) -> bool {
-        ASSERT((x.isNumber() || x.isBigInt()) && (y.isNumber() || y.isBigInt()));
-        if (!defaultSort) {
-            Value args[] = { x, y };
-            double v = Object::call(state, cmpfn, Value(), 2, args).toNumber(state);
-            buffer->throwTypeErrorIfDetached(state);
-            if (std::isnan(v)) {
-                return false;
-            }
-            return (v < 0);
-        } else {
-            if (LIKELY(x.isNumber())) {
-                double xNum = x.asNumber();
-                double yNum = y.asNumber();
-
-                // 22.2.3.25.3-10
-                if (std::isnan(xNum)) {
-                    return false;
-                }
-
-                if (std::isnan(yNum)) {
-                    return true;
-                }
-
-                if (xNum == 0.0 && xNum == yNum) {
-                    return std::signbit(xNum);
-                }
-
-                return xNum <= yNum;
-            } else {
-                return x.asBigInt()->lessThanEqual(y.asBigInt());
-            }
-        } });
-    return O;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.subarray
-static Value builtinTypedArraySubArray(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the this value.
-    RESOLVE_THIS_BINDING_TO_TYPEDARRAY(O, TypedArray, subarray);
-
-    // Let buffer be O.[[ViewedArrayBuffer]].
-    ArrayBufferObject* buffer = O->buffer();
-    // Let srcLength be O.[[ArrayLength]].
-    double srcLength = O->arrayLength();
-    // Let relativeBegin be ToInteger(begin).
-    double relativeBegin = argv[0].toInteger(state);
-    // If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin), 0); else let beginIndex be min(relativeBegin, srcLength).
-    double beginIndex = (relativeBegin < 0) ? std::max((srcLength + relativeBegin), 0.0) : std::min(relativeBegin, srcLength);
-    // If end is undefined, let relativeEnd be srcLength; else, let relativeEnd be ToInteger(end).
-    double relativeEnd = srcLength;
-    if (!argv[1].isUndefined()) {
-        relativeEnd = argv[1].toInteger(state);
-    }
-    // If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd), 0); else let endIndex be min(relativeEnd, srcLength).
-    double endIndex = (relativeEnd < 0) ? std::max((srcLength + relativeEnd), 0.0) : std::min(relativeEnd, srcLength);
-
-    // Let newLength be max(endIndex – beginIndex, 0).
-    double newLength = std::max((int)(endIndex - beginIndex), 0);
-
-    // Let constructorName be the String value of O’s [[TypedArrayName]] internal slot.
-    // Let elementSize be the Number value of the Element Size value specified in Table 49 for constructorName.
-    size_t elementSize = O->elementSize();
-    // Let srcByteOffset be the value of O’s [[ByteOffset]] internal slot.
-    size_t srcByteOffset = O->byteOffset();
-    // Let beginByteOffset be srcByteOffset + beginIndex × elementSize.
-    size_t beginByteOffset = srcByteOffset + beginIndex * elementSize;
-
-    // Let argumentsList be «buffer, beginByteOffset, newLength».
-    Value args[3] = { buffer, Value(beginByteOffset), Value(newLength) };
-    // Return ? TypedArraySpeciesCreate(O, argumentsList).
-    return TypedArraySpeciesCreate(state, O, 3, args);
-}
-
-static Value builtinTypedArrayEvery(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, every);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.every as defined in 22.1.3.5 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    unsigned len = O->asTypedArrayObject()->arrayLength();
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
-                                       state.context()->staticStrings().every.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1)
-        T = argv[1];
-
-    // Let k be 0.
-    size_t k = 0;
-
-    while (k < len) {
-        ObjectGetResult value = O->getIndexedProperty(state, Value(k));
-        // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-        Value kValue = value.value(state, O);
-        // Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
-        Value args[] = { kValue, Value(k), O };
-        Value testResult = Object::call(state, callbackfn, T, 3, args);
-
-        if (!testResult.toBoolean(state)) {
-            return Value(false);
-        }
-
-        // Increae k by 1.
-        k++;
-    }
-    return Value(true);
-}
-
-//https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.fill
-static Value builtinTypedArrayFill(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
-
-    // Let len be O.[[ArrayLength]].
-    size_t len = O->arrayLength();
-
-    Value value(Value::ForceUninitialized);
-    // If O.[[TypedArrayName]] is "BigUint64Array" or "BigInt64Array", let value be ? ToBigInt(value).
-    auto typedArrayType = O->asTypedArrayObject()->typedArrayType();
-    if (UNLIKELY(typedArrayType == TypedArrayType::BigInt64 || typedArrayType == TypedArrayType::BigUint64)) {
-        value = argv[0].toBigInt(state);
-    } else {
-        // Otherwise, let value be ? ToNumber(value).
-        // Set value to ? ToNumber(value).
-        value = Value(argv[0].toNumber(state));
-    }
-    // Let relativeStart be ? ToInteger(start).
-    double relativeStart = 0;
-    if (argc > 1) {
-        relativeStart = argv[1].toInteger(state);
-    }
-    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
-    size_t k = (relativeStart < 0) ? std::max(len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
-    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
-    double relativeEnd = len;
-    if (argc > 2 && !argv[2].isUndefined()) {
-        relativeEnd = argv[2].toInteger(state);
-    }
-    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
-    size_t fin = (relativeEnd < 0) ? std::max(len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
-
-    // If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, throw a TypeError exception.
-    O->buffer()->throwTypeErrorIfDetached(state);
-
-    // Repeat, while k < final
-    while (k < fin) {
-        O->setIndexedPropertyThrowsException(state, Value(k), value);
-        k++;
-    }
-    // return O.
-    return O;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.filter
-static Value builtinTypedArrayFilter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
-
-    // Let len be O.[[ArrayLength]].
-    size_t len = O->arrayLength();
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().filter.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let kept be a new empty List.
-    ValueVectorWithInlineStorage kept;
-    // Let k be 0.
-    size_t k = 0;
-    // Let captured be 0.
-    size_t captured = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
-        Value args[] = { kValue, Value(k), O };
-        bool selected = Object::call(state, callbackfn, T, 3, args).toBoolean(state);
-        if (selected) {
-            kept.push_back(kValue);
-            captured++;
-        }
-        k++;
-    }
-
-    // Let A be ? TypedArraySpeciesCreate(O, « captured »).
-    Value arg[1] = { Value(captured) };
-    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
-
-    // Let n be 0.
-    // For each element e of kept
-    for (size_t n = 0; n < kept.size(); n++) {
-        // Let status be Set(A, ToString(n), e, true ).
-        A.asObject()->setIndexedPropertyThrowsException(state, Value(n), kept[n]);
-    }
-    // Return A.
-    return A;
-}
-
-static Value builtinTypedArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, find);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.find as defined in 22.1.3.8 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    // If IsCallable(predicate) is false, throw a TypeError exception.
-    Value predicate = argv[0];
-    if (!predicate.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let k be 0.
-    size_t k = 0;
-    Value kValue;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let kValue be Get(O, Pk).
-        kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
-        // Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
-        Value args[] = { kValue, Value(k), O };
-        bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
-        // If testResult is true, return kValue.
-        if (testResult) {
-            return kValue;
-        }
-        // Increase k by 1.
-        k++;
-    }
-    // Return undefined.
-    return Value();
-}
-
-static Value builtinTypedArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, findIndex);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.findIndex as defined in 22.1.3.9 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    // If IsCallable(predicate) is false, throw a TypeError exception.
-    Value predicate = argv[0];
-    if (!predicate.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let k be 0.
-    size_t k = 0;
-    Value kValue;
-    // Repeat, while k < len
-    while (k < len) {
-        // Let kValue be ? Get(O, Pk).
-        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
-        // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
-        Value args[] = { kValue, Value(k), O };
-        bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
-        // If testResult is true, return k.
-        if (testResult) {
-            return Value(k);
-        }
-        // Increase k by 1.
-        k++;
-    }
-    // Return -1
-    return Value(-1);
-}
-
-static Value builtinTypedArrayForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, forEach);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.forEach as defined in 22.1.3.10 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
-                                       state.context()->staticStrings().forEach.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let k be 0.
-    size_t k = 0;
-    while (k < len) {
-        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
-        Value kValue = res.value(state, O);
-        Value args[] = { kValue, Value(k), O };
-        Object::call(state, callbackfn, T, 3, args);
-        k++;
-    }
-    // Return undefined.
-    return Value();
-}
-
-static Value builtinTypedArrayJoin(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, join);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.join as defined in 22.1.3.12 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    Value separator = argv[0];
-    size_t lenMax = STRING_MAXIMUM_LENGTH;
-    String* sep;
-
-    if (separator.isUndefined()) {
-        sep = state.context()->staticStrings().asciiTable[(size_t)','].string();
-    } else {
-        sep = separator.toString(state);
-    }
-
-    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(O) || len == 0) {
-        return String::emptyString;
-    }
-    ToStringRecursionPreventerItemAutoHolder holder(state, O);
-
-    StringBuilder builder;
-    Value elem = O->getIndexedProperty(state, Value(0)).value(state, O);
-    if (elem.isUndefinedOrNull()) {
-        elem = String::emptyString;
-    }
-    builder.appendString(elem.toString(state));
-
-    size_t curIndex = 1;
-    while (curIndex < len) {
-        if (sep->length() > 0) {
-            if (static_cast<double>(builder.contentLength()) > static_cast<double>(lenMax - sep->length())) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::String_InvalidStringLength);
-            }
-            builder.appendString(sep);
-        }
-        elem = O->getIndexedProperty(state, Value(curIndex)).value(state, O);
-        if (elem.isUndefinedOrNull()) {
-            elem = String::emptyString;
-        }
-        builder.appendString(elem.toString(state));
-        curIndex++;
-    }
-
-    return builder.finalize(&state);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.map
-static Value builtinTypedArrayMap(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
-
-    // Let len be O.[[ArrayLength]].
-    size_t len = O->arrayLength();
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().map.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If thisArg was supplied, let T be thisArg; else let T be undefined.
-    Value T;
-    if (argc > 1) {
-        T = argv[1];
-    }
-
-    // Let A be ? TypedArraySpeciesCreate(O, « len »).
-    Value arg[1] = { Value(len) };
-    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
-
-    // Let k be 0.
-    size_t k = 0;
-    // Repeat, while k < len
-    while (k < len) {
-        Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
-        Value args[] = { kValue, Value(k), O };
-        Value mappedValue = Object::call(state, callbackfn, T, 3, args);
-        A.asObject()->setIndexedPropertyThrowsException(state, Value(k), mappedValue);
-        k++;
-    }
-    // Return A.
-    return A;
-}
-
-static Value builtinTypedArrayReduce(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reduce);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.reduce as defined in 22.1.3.18 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    if (len == 0 && argc < 2) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduce.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-    }
-
-    size_t k = 0; // 6
-    Value accumulator;
-    if (argc > 1) { // 7
-        accumulator = argv[1];
-    } else { // 8
-        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
-        accumulator = res.value(state, O);
-        k++;
-    }
-    while (k < len) { // 9
-        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
-        Value kValue = res.value(state, O);
-        Value args[] = { accumulator, kValue, Value(k), O };
-        accumulator = Object::call(state, callbackfn, Value(), 4, args);
-        k++;
-    }
-    return accumulator;
-}
-
-static Value builtinTypedArrayReduceRight(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reduceRight);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.reduceRight as defined in 22.1.3.19 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    double len = O->asTypedArrayObject()->arrayLength();
-
-    // If IsCallable(callbackfn) is false, throw a TypeError exception.
-    Value callbackfn = argv[0];
-    if (!callbackfn.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true,
-                                       state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
-    }
-
-    // If len is 0 and initialValue is not present, throw a TypeError exception.
-    if (len == 0 && argc < 2) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().reduceRight.string(), ErrorObject::Messages::GlobalObject_ReduceError);
-    }
-
-    // Let k be len-1.
-    int64_t k = len - 1;
-
-    Value accumulator;
-    // If initialValue is present, then
-    if (argc > 1) {
-        // Set accumulator to initialValue.
-        accumulator = argv[1];
-    } else {
-        // Else, initialValue is not present
-        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
-        accumulator = res.value(state, O);
-        k--;
-    }
-
-    // Repeat, while k ≥ 0
-    while (k >= 0) {
-        ObjectGetResult res = O->getIndexedProperty(state, Value(k));
-        Value kValue = res.value(state, O);
-        Value args[] = { accumulator, kValue, Value(k), O };
-        accumulator = Object::call(state, callbackfn, Value(), 4, args);
-        k--;
-    }
-    // Return accumulator.
-    return accumulator;
-}
-
-static Value builtinTypedArrayReverse(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, reverse);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, O);
-
-    // Array.prototype.reverse as defined in 22.1.3.20 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    size_t len = O->asTypedArrayObject()->arrayLength();
-    size_t middle = std::floor(len / 2);
-    size_t lower = 0;
-    while (middle > lower) {
-        size_t upper = len - lower - 1;
-
-        ObjectGetResult upperResult = O->getIndexedProperty(state, Value(upper));
-        ObjectGetResult lowerResult = O->getIndexedProperty(state, Value(lower));
-        RELEASE_ASSERT(upperResult.hasValue() && lowerResult.hasValue());
-
-        Value upperValue = upperResult.value(state, O);
-        Value lowerValue = lowerResult.value(state, O);
-
-        if (!O->setIndexedProperty(state, Value(lower), upperValue)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::DefineProperty_NotWritable);
-        }
-        if (!O->setIndexedProperty(state, Value(upper), lowerValue)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::DefineProperty_NotWritable);
-        }
-
-        lower++;
-    }
-    return O;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.slice
-static Value builtinTypedArraySlice(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be the this value.
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    TypedArrayObject* O = thisValue.asObject()->asTypedArrayObject();
-
-    // Let len be the value of O’s [[ArrayLength]] internal slot.
-    size_t len = O->arrayLength();
-    // Let relativeStart be ToInteger(start).
-    double relativeStart = argv[0].toInteger(state);
-    // If relativeStart < 0, let k be max((len + relativeStart),0); else let k be min(relativeStart, len).
-    size_t k = (relativeStart < 0) ? std::max((double)len + relativeStart, 0.0) : std::min(relativeStart, (double)len);
-    // If end is undefined, let relativeEnd be len; else let relativeEnd be ToInteger(end).
-    double relativeEnd = (argv[1].isUndefined()) ? len : argv[1].toInteger(state);
-    // If relativeEnd < 0, let final be max((len + relativeEnd),0); else let final be min(relativeEnd, len).
-    double finalEnd = (relativeEnd < 0) ? std::max((double)len + relativeEnd, 0.0) : std::min(relativeEnd, (double)len);
-    // Let count be max(final – k, 0).
-    size_t count = std::max((double)finalEnd - k, 0.0);
-
-    Value arg[1] = { Value(count) };
-    Value A = TypedArraySpeciesCreate(state, O, 1, arg);
-    TypedArrayObject* target = A.asObject()->asTypedArrayObject();
-
-    // If SameValue(srcType, targetType) is false, then
-    if (O->typedArrayType() != target->typedArrayType()) {
-        size_t n = 0;
-        while (k < finalEnd) {
-            O->buffer()->throwTypeErrorIfDetached(state);
-            Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
-            A.asObject()->setIndexedPropertyThrowsException(state, Value(n), kValue);
-            k++;
-            n++;
-        }
-    } else if (count > 0) {
-        // Else if count > 0,
-        ArrayBufferObject* srcBuffer = O->buffer();
-        srcBuffer->throwTypeErrorIfDetached(state);
-        ArrayBufferObject* targetBuffer = target->buffer();
-
-        size_t elementSize = O->elementSize();
-        size_t srcByteOffset = O->byteOffset();
-        size_t targetByteIndex = target->byteOffset();
-        size_t srcByteIndex = (size_t)k * elementSize + srcByteOffset;
-        size_t limit = targetByteIndex + count * elementSize;
-
-        while (targetByteIndex < limit) {
-            // Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, "Uint8", true, "Unordered").
-            Value value = srcBuffer->getValueFromBuffer(state, srcByteIndex, TypedArrayType::Uint8);
-            // Perform SetValueInBuffer(targetBuffer, targetByteIndex, "Uint8", value, true, "Unordered").
-            targetBuffer->setValueInBuffer(state, targetByteIndex, TypedArrayType::Uint8, value);
-            srcByteIndex++;
-            targetByteIndex++;
-        }
-    }
-
-    return A;
-}
-
-static Value builtinTypedArrayToLocaleString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Let O be ToObject(this value).
-    RESOLVE_THIS_BINDING_TO_OBJECT(array, TypedArray, toLocaleString);
-    // validateTypedArray is applied to the this value prior to evaluating the algorithm.
-    TypedArrayObject::validateTypedArray(state, array);
-
-    // Array.prototype.toLocaleString as defined in 22.1.3.26 except
-    // that the this object’s [[ArrayLength]] internal slot is accessed
-    // in place of performing a [[Get]] of "length"
-    size_t len = array->asTypedArrayObject()->arrayLength();
-
-    if (!state.context()->toStringRecursionPreventer()->canInvokeToString(array)) {
-        return String::emptyString;
-    }
-    ToStringRecursionPreventerItemAutoHolder holder(state, array);
-
-    // Let separator be the String value for the list-separator String appropriate for the host environment’s current locale (this is derived in an implementation-defined way).
-    String* separator = state.context()->staticStrings().asciiTable[(size_t)','].string();
-
-    // Let R be the empty String.
-    String* R = String::emptyString;
-
-    // Let k be 0.
-    size_t k = 0;
-
-    // Repeat, while k < len
-    while (k < len) {
-        // If k > 0, then
-        if (k > 0) {
-            // Set R to the string-concatenation of R and separator.
-            StringBuilder builder;
-            builder.appendString(R);
-            builder.appendString(separator);
-            R = builder.finalize(&state);
-        }
-        // Let nextElement be ? Get(array, ! ToString(k)).
-        Value nextElement = array->getIndexedProperty(state, Value(k)).value(state, array);
-        // If nextElement is not undefined or null, then
-        ASSERT(!nextElement.isUndefinedOrNull());
-        // Let S be ? ToString(? Invoke(nextElement, "toLocaleString")).
-        Value func = nextElement.toObject(state)->get(state, state.context()->staticStrings().toLocaleString).value(state, nextElement);
-        String* S = Object::call(state, func, nextElement, 0, nullptr).toString(state);
-        // Set R to the string-concatenation of R and S.
-        StringBuilder builder2;
-        builder2.appendString(R);
-        builder2.appendString(S);
-        R = builder2.finalize(&state);
-        // Increase k by 1.
-        k++;
-    }
-
-    // Return R.
-    return R;
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.keys
-static Value builtinTypedArrayKeys(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    // Return CreateArrayIterator(O, "key").
-    return thisValue.asObject()->keys(state);
-}
-
-static Value builtinTypedArrayValues(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // Perform ? TypedArrayObject::validateTypedArray(O).
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    return thisValue.asObject()->values(state);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.entries
-static Value builtinTypedArrayEntries(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    return thisValue.asObject()->entries(state);
-}
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-get-%typedarray%.prototype-@@tostringtag
-static Value builtinTypedArrayToStringTagGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    Value O = thisValue;
-    if (!O.isObject()) {
-        return Value();
-    }
-
-    if (O.asObject()->isTypedArrayObject()) {
-        return Value(O.asObject()->asTypedArrayObject()->typedArrayName(state));
-    }
-    return Value();
-}
-
-static Value builtinTypedArrayAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    TypedArrayObject::validateTypedArray(state, thisValue);
-    Object* obj = thisValue.asObject();
-    size_t len = obj->length(state);
-    double relativeStart = argv[0].toInteger(state);
-    if (relativeStart < 0) {
-        relativeStart = len + relativeStart;
-    }
-    if (relativeStart < 0 || relativeStart >= len) {
-        return Value();
-    }
-    return obj->getIndexedProperty(state, Value(relativeStart)).value(state, thisValue);
-}
-
-template <typename TA, int elementSize>
-FunctionObject* GlobalObject::installTypedArray(ExecutionState& state, AtomicString taName, Object** proto, FunctionObject* typedArrayFunction)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-    NativeFunctionObject* taConstructor = new NativeFunctionObject(state, NativeFunctionInfo(taName, builtinTypedArrayConstructor<TA>, 3), NativeFunctionObject::__ForBuiltinConstructor__);
-    taConstructor->setGlobalIntrinsicObject(state);
-
-    *proto = m_objectPrototype;
-    Object* taPrototype = new TypedArrayPrototypeObject(state);
-    taPrototype->setGlobalIntrinsicObject(state, true);
-    taPrototype->setPrototype(state, typedArrayFunction->getFunctionPrototype(state));
-
-    taConstructor->setPrototype(state, typedArrayFunction); // %TypedArray%
-    taConstructor->setFunctionPrototype(state, taPrototype);
-
-    // 22.2.5.1 /TypedArray/.BYTES_PER_ELEMENT
-    taConstructor->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->BYTES_PER_ELEMENT), ObjectPropertyDescriptor(Value(elementSize), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ValuePresent)));
-
-    // 22.2.6.1 /TypedArray/.prototype.BYTES_PER_ELEMENT
-    taPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->BYTES_PER_ELEMENT), ObjectPropertyDescriptor(Value(elementSize), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ValuePresent)));
-
-    // 22.2.6.2 /TypedArray/.prototype.constructor
-    taPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    defineOwnProperty(state, ObjectPropertyName(taName),
-                      ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    return taConstructor;
-}
-
-void GlobalObject::installTypedArray(ExecutionState& state)
-{
-    const StaticStrings* strings = &state.context()->staticStrings();
-
-    // %TypedArray%
-    FunctionObject* typedArrayFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->TypedArray, builtinTypedArrayConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    typedArrayFunction->setGlobalIntrinsicObject(state);
-
-    typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->from),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->from, builtinTypedArrayFrom, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->of),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->of, builtinTypedArrayOf, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getSymbolSpecies, builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)), Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayFunction->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
-    }
-
-
-    // %TypedArray%.prototype
-    Object* typedArrayPrototype = typedArrayFunction->getFunctionPrototype(state).asObject();
-    typedArrayPrototype->setGlobalIntrinsicObject(state, true);
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->subarray),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->subarray, builtinTypedArraySubArray, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->set),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->set, builtinTypedArraySet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->some),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->some, builtinTypedArraySome, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->sort),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->sort, builtinTypedArraySort, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->copyWithin),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->copyWithin, builtinTypedArrayCopyWithin, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->every),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->every, builtinTypedArrayEvery, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->fill),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->fill, builtinTypedArrayFill, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->filter),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->filter, builtinTypedArrayFilter, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->find),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->find, builtinTypedArrayFind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->findIndex),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->findIndex, builtinTypedArrayFindIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->forEach),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->forEach, builtinTypedArrayForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->join),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->join, builtinTypedArrayJoin, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->map),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->map, builtinTypedArrayMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reduce),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reduce, builtinTypedArrayReduce, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reduceRight),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reduceRight, builtinTypedArrayReduceRight, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->reverse),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->reverse, builtinTypedArrayReverse, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->slice),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->slice, builtinTypedArraySlice, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toLocaleString),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->toLocaleString, builtinTypedArrayToLocaleString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.tostring
-    // The initial value of the %TypedArray%.prototype.toString data property is the same built-in function object as the Array.prototype.toString method
-    ASSERT(!!m_arrayPrototype && m_arrayPrototype->hasOwnProperty(state, ObjectPropertyName(strings->toString)));
-    Value arrayToString = m_arrayPrototype->getOwnProperty(state, ObjectPropertyName(strings->toString)).value(state, m_arrayPrototype);
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
-                                                          ObjectPropertyDescriptor(arrayToString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->indexOf),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->indexOf, builtinTypedArrayIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->lastIndexOf),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lastIndexOf, builtinTypedArrayLastIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->includes),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->includes, builtinTypedArrayIncludes, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->keys),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->keys, builtinTypedArrayKeys, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->entries),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->entries, builtinTypedArrayEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->at),
-                                                          ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->at, builtinTypedArrayAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-
-    auto valuesFn = new NativeFunctionObject(state, NativeFunctionInfo(strings->values, builtinTypedArrayValues, 0, NativeFunctionInfo::Strict));
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->values),
-                                                          ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
-                                                          ObjectPropertyDescriptor(valuesFn,
-                                                                                   (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getSymbolToStringTag, builtinTypedArrayToStringTagGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag), desc);
-    }
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteLength, builtinTypedArrayByteLengthGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor byteLengthDesc2(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteLength), byteLengthDesc2);
-    }
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getbyteOffset, builtinTypedArrayByteOffsetGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor byteOffsetDesc2(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteOffset), byteOffsetDesc2);
-    }
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getLength, builtinTypedArrayLengthGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor lengthDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->length), lengthDesc);
-    }
-    {
-        JSGetterSetter gs(
-            new NativeFunctionObject(state, NativeFunctionInfo(strings->getBuffer, builtinTypedArrayBufferGetter, 0, NativeFunctionInfo::Strict)),
-            Value(Value::EmptyValue));
-        ObjectPropertyDescriptor bufferDesc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
-        typedArrayPrototype->defineOwnProperty(state, ObjectPropertyName(strings->buffer), bufferDesc);
-    }
-
-    m_typedArray = typedArrayFunction;
-    m_typedArrayPrototype = typedArrayFunction->getFunctionPrototype(state).asObject();
-#define INSTALL_TYPEDARRAY(TYPE, type, siz, nativeType)                                                                                      \
-    m_##type##Array = installTypedArray<TYPE##ArrayObject, siz>(state, strings->TYPE##Array, &m_##type##ArrayPrototype, typedArrayFunction); \
-    m_##type##ArrayPrototype = m_##type##Array->getFunctionPrototype(state).asObject();
-
-    FOR_EACH_TYPEDARRAY_TYPES(INSTALL_TYPEDARRAY)
-#undef INSTALL_TYPEDARRAY
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakMap.cpp
deleted file mode 100644 (file)
index 56b67d5..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "WeakMapObject.h"
-#include "IteratorObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    // Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
-    // Set map's [[MapData]] internal slot to a new empty List.
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->weakMapPrototype();
-    });
-    WeakMapObject* map = new WeakMapObject(state, proto);
-
-    // If iterable is not present, or is either undefined or null, return map.
-    if (argc == 0 || argv[0].isUndefinedOrNull()) {
-        return map;
-    }
-
-    Value iterable = argv[0];
-
-    // Let adder be ? Get(map, "set").
-    Value adder = map->Object::get(state, ObjectPropertyName(state.context()->staticStrings().set)).value(state, map);
-    // If IsCallable(adder) is false, throw a TypeError exception.
-    if (!adder.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
-    }
-
-    // Let iteratorRecord be ? GetIterator(iterable).
-    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
-    while (true) {
-        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
-        if (!next.hasValue()) {
-            return map;
-        }
-
-        Value nextItem = IteratorObject::iteratorValue(state, next.value());
-        if (!nextItem.isObject()) {
-            ErrorObject* errorobj = ErrorObject::createError(state, ErrorObject::TypeError, new ASCIIString("TypeError"));
-            return IteratorObject::iteratorClose(state, iteratorRecord, errorobj, true);
-        }
-
-        try {
-            // Let k be Get(nextItem, "0").
-            // If k is an abrupt completion, return ? IteratorClose(iter, k).
-            Value k = nextItem.asObject()->getIndexedProperty(state, Value(0)).value(state, nextItem);
-            // Let v be Get(nextItem, "1").
-            // If v is an abrupt completion, return ? IteratorClose(iter, v).
-            Value v = nextItem.asObject()->getIndexedProperty(state, Value(1)).value(state, nextItem);
-
-            // Let status be Call(adder, map, « k.[[Value]], v.[[Value]] »).
-            Value argv[2] = { k, v };
-            Object::call(state, adder, map, 2, argv);
-        } catch (const Value& v) {
-            // we should save thrown value bdwgc cannot track thrown value
-            Value exceptionValue = v;
-            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
-            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-        }
-    }
-
-    return map;
-}
-
-#define RESOLVE_THIS_BINDING_TO_WEAKMAP(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                      \
-    if (!thisValue.isObject() || !thisValue.asObject()->isWeakMapObject()) {                                                                                                                                                                             \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                    \
-    WeakMapObject* NAME = thisValue.asObject()->asWeakMapObject();
-
-static Value builtinWeakMapDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, stringDelete);
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-
-    return Value(M->deleteOperation(state, argv[0].asObject()));
-}
-
-static Value builtinWeakMapGet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, get);
-    if (!argv[0].isObject()) {
-        return Value();
-    }
-
-    return M->get(state, argv[0].asObject());
-}
-
-static Value builtinWeakMapHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, has);
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-
-    return Value(M->has(state, argv[0].asObject()));
-}
-
-static Value builtinWeakMapSet(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKMAP(M, WeakMap, set);
-    if (!argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Invalid value used as weak map key");
-    }
-
-    M->set(state, argv[0].asObject(), argv[1]);
-    return M;
-}
-
-void GlobalObject::installWeakMap(ExecutionState& state)
-{
-    m_weakMap = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakMap, builtinWeakMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_weakMap->setGlobalIntrinsicObject(state);
-
-    m_weakMapPrototype = new Object(state, m_objectPrototype);
-    m_weakMapPrototype->setGlobalIntrinsicObject(state, true);
-    m_weakMapPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinWeakMapDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().get),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get, builtinWeakMapGet, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinWeakMapHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().set),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().set, builtinWeakMapSet, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMapPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakMap.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakMap->setFunctionPrototype(state, m_weakMapPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap),
-                      ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakRef.cpp
deleted file mode 100644 (file)
index 6bb73bb..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "WeakRefObject.h"
-#include "NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinWeakRefConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-    if (argc == 0 || !argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "target is not object");
-    }
-
-    // Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRefPrototype%", « [[WeakRefTarget]] »).
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->weakRefPrototype();
-    });
-    WeakRefObject* weakRef = new WeakRefObject(state, proto, argv[0].asObject());
-
-    return weakRef;
-}
-
-
-static Value builtinWeakRefDeRef(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    if (!thisValue.isObject() || !thisValue.asObject()->isWeakRefObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver);
-    }
-    // Let weakRef be the this value.
-    WeakRefObject* weakRef = thisValue.asObject()->asWeakRefObject();
-    return weakRef->targetAsValue();
-}
-
-
-void GlobalObject::installWeakRef(ExecutionState& state)
-{
-    m_weakRef = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakRef, builtinWeakRefConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_weakRef->setGlobalIntrinsicObject(state);
-
-    m_weakRefPrototype = new Object(state, m_objectPrototype);
-    m_weakRefPrototype->setGlobalIntrinsicObject(state, true);
-    m_weakRefPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakRefPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().deref),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().deref, builtinWeakRefDeRef, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    // WeakRef.prototype.deref
-    m_weakRefPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakRef.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakRef->setFunctionPrototype(state, m_weakRefPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakRef),
-                      ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/GlobalObjectBuiltinWeakSet.cpp
deleted file mode 100644 (file)
index a60f2f3..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "GlobalObject.h"
-#include "Context.h"
-#include "VMInstance.h"
-#include "WeakSetObject.h"
-#include "IteratorObject.h"
-#include "NativeFunctionObject.h"
-#include "ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-// https://www.ecma-international.org/ecma-262/10.0/#sec-weakset-constructor
-static Value builtinWeakSetConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    // If NewTarget is undefined, throw a TypeError exception.
-    if (!newTarget.hasValue()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
-    }
-
-    // Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSetPrototype%", « [[WeakSetData]] »).
-    // Set set's [[WeakSetData]] internal slot to a new empty List.
-    Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
-        return constructorRealm->globalObject()->weakSetPrototype();
-    });
-    WeakSetObject* set = new WeakSetObject(state, proto);
-
-    // If iterable is not present, let iterable be undefined.
-    Value iterable;
-    if (argc > 0) {
-        iterable = argv[0];
-    }
-
-    // If iterable is either undefined or null, return set.
-    if (iterable.isUndefinedOrNull()) {
-        return set;
-    }
-
-    // Let adder be ? Get(set, "add").
-    Value adder = set->get(state, ObjectPropertyName(state.context()->staticStrings().add)).value(state, set);
-    // If IsCallable(adder) is false, throw a TypeError exception.
-    if (!adder.isCallable()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::NOT_Callable);
-    }
-
-    // Let iteratorRecord be ? GetIterator(iterable).
-    auto iteratorRecord = IteratorObject::getIterator(state, iterable);
-
-    // Repeat
-    while (true) {
-        // Let next be ? IteratorStep(iteratorRecord).
-        auto next = IteratorObject::iteratorStep(state, iteratorRecord);
-        // If next is false, return set.
-        if (!next.hasValue()) {
-            return set;
-        }
-        // Let nextValue be ? IteratorValue(next).
-        Value nextValue = IteratorObject::iteratorValue(state, next.value());
-
-        // Let status be Call(adder, set, « nextValue »).
-        try {
-            Value argv[1] = { nextValue };
-            Object::call(state, adder, set, 1, argv);
-        } catch (const Value& v) {
-            // we should save thrown value bdwgc cannot track thrown value
-            Value exceptionValue = v;
-            // If status is an abrupt completion, return ? IteratorClose(iteratorRecord, status).
-            return IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
-        }
-    }
-    return set;
-}
-
-#define RESOLVE_THIS_BINDING_TO_WEAKSET(NAME, OBJ, BUILT_IN_METHOD)                                                                                                                                                                                      \
-    if (!thisValue.isObject() || !thisValue.asObject()->isWeakSetObject()) {                                                                                                                                                                             \
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().OBJ.string(), true, state.context()->staticStrings().BUILT_IN_METHOD.string(), ErrorObject::Messages::GlobalObject_CalledOnIncompatibleReceiver); \
-    }                                                                                                                                                                                                                                                    \
-    WeakSetObject* NAME = thisValue.asObject()->asWeakSetObject();
-
-static Value builtinWeakSetAdd(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, add);
-    if (!argv[0].isObject()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Invalid value used as weak set key");
-    }
-
-    S->add(state, argv[0].asObject());
-    return S;
-}
-
-static Value builtinWeakSetDelete(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, stringDelete);
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-
-    return Value(S->deleteOperation(state, argv[0].asObject()));
-}
-
-static Value builtinWeakSetHas(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
-    RESOLVE_THIS_BINDING_TO_WEAKSET(S, WeakSet, has);
-    if (!argv[0].isObject()) {
-        return Value(false);
-    }
-
-    return Value(S->has(state, argv[0].asObject()));
-}
-
-void GlobalObject::installWeakSet(ExecutionState& state)
-{
-    m_weakSet = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakSet, builtinWeakSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
-    m_weakSet->setGlobalIntrinsicObject(state);
-
-    m_weakSetPrototype = new Object(state);
-    m_weakSetPrototype->setGlobalIntrinsicObject(state, true);
-
-    m_weakSetPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinWeakSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().has),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinWeakSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().add),
-                                                         ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinWeakSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakSetPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
-                                                         ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakSet.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
-
-    m_weakSet->setFunctionPrototype(state, m_weakSetPrototype);
-    defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakSet),
-                      ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.cpp
deleted file mode 100644 (file)
index 533e1e8..0000000
+++ /dev/null
@@ -1,2030 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "runtime/Context.h"
-#include "runtime/ExecutionState.h"
-#include "runtime/Value.h"
-#include "runtime/Object.h"
-#include "runtime/ArrayObject.h"
-#include "runtime/Intl.h"
-#include "runtime/VMInstance.h"
-#include "runtime/IntlLocale.h"
-
-namespace Escargot {
-
-// Invalid tags starting with: https://github.com/tc39/ecma402/pull/289
-static bool isValidTagInBCP47ButInvalidOnUTS35(const std::string& s)
-{
-    if (s.rfind("no-nyn", 0) == 0) {
-        return true;
-    } else if (s.rfind("i-klingon", 0) == 0) {
-        return true;
-    } else if (s.rfind("zh-hak-CN", 0) == 0) {
-        return true;
-    } else if (s.rfind("sgn-ils", 0) == 0) {
-        return true;
-    }
-
-    return false;
-}
-
-static std::string grandfatheredLangTag(const std::string& locale)
-{
-    // grandfathered = irregular / regular
-    std::unordered_map<std::string, std::string> tagMap;
-    // Irregular.
-    tagMap["en-gb-oed"] = "en-GB-oed";
-    tagMap["i-ami"] = "ami";
-    tagMap["i-bnn"] = "bnn";
-    tagMap["i-default"] = "i-default";
-    tagMap["i-enochian"] = "i-enochian";
-    tagMap["i-hak"] = "hak";
-    tagMap["i-klingon"] = "tlh";
-    tagMap["i-lux"] = "lb";
-    tagMap["i-mingo"] = "i-mingo";
-    tagMap["i-navajo"] = "nv";
-    tagMap["i-pwn"] = "pwn";
-    tagMap["i-tao"] = "tao";
-    tagMap["i-tay"] = "tay";
-    tagMap["i-tsu"] = "tsu";
-    tagMap["sgn-be-fr"] = "sfb";
-    tagMap["sgn-be-nl"] = "vgt";
-    tagMap["sgn-ch-de"] = "sgg";
-    // Regular.
-    tagMap["art-lojban"] = "jbo";
-    tagMap["cel-gaulish"] = "xtg-x-cel-gaulish";
-    tagMap["no-bok"] = "nb";
-    tagMap["no-nyn"] = "nn";
-    tagMap["zh-guoyu"] = "zh";
-    tagMap["zh-hakka"] = "hak";
-    tagMap["zh-min"] = "zh-min";
-    tagMap["zh-min-nan"] = "nan";
-    tagMap["zh-xiang"] = "hsn";
-
-    auto tempLocale = locale;
-    std::transform(tempLocale.begin(), tempLocale.end(), tempLocale.begin(), tolower);
-    auto iter = tagMap.find(tempLocale);
-
-    if (iter != tagMap.end()) {
-        return iter->second;
-    }
-    return std::string();
-}
-
-static std::string intlPreferredLanguageTag(const std::string& tag)
-{
-    // 78 possible replacements
-    if (tag == "aar")
-        return "aa";
-    if (tag == "aam")
-        return "aas";
-    if (tag == "adp")
-        return "dz";
-    if (tag == "aue")
-        return "ktz";
-    if (tag == "ayx")
-        return "nun";
-    if (tag == "bgm")
-        return "bcg";
-    if (tag == "bjd")
-        return "drl";
-    if (tag == "ccq")
-        return "rki";
-    if (tag == "ces")
-        return "cs";
-    if (tag == "cjr")
-        return "mom";
-    if (tag == "cka")
-        return "cmr";
-    if (tag == "cmk")
-        return "xch";
-    if (tag == "cmn")
-        return "zh";
-    if (tag == "coy")
-        return "pij";
-    if (tag == "cqu")
-        return "quh";
-    if (tag == "drh")
-        return "khk";
-    if (tag == "drw")
-        return "prs";
-    if (tag == "gav")
-        return "dev";
-    if (tag == "gfx")
-        return "vaj";
-    if (tag == "ggn")
-        return "gvr";
-    if (tag == "gti")
-        return "nyc";
-    if (tag == "guv")
-        return "duz";
-    if (tag == "heb")
-        return "he";
-    if (tag == "hrr")
-        return "jal";
-    if (tag == "ibi")
-        return "opa";
-    if (tag == "ilw")
-        return "gal";
-    if (tag == "in")
-        return "id";
-    if (tag == "iw")
-        return "he";
-    if (tag == "jeg")
-        return "oyb";
-    if (tag == "ji")
-        return "yi";
-    if (tag == "jw")
-        return "jv";
-    if (tag == "kgc")
-        return "tdf";
-    if (tag == "kgh")
-        return "kml";
-    if (tag == "koj")
-        return "kwv";
-    if (tag == "krm")
-        return "bmf";
-    if (tag == "ktr")
-        return "dtp";
-    if (tag == "kvs")
-        return "gdj";
-    if (tag == "kwq")
-        return "yam";
-    if (tag == "kxe")
-        return "tvd";
-    if (tag == "kzj")
-        return "dtp";
-    if (tag == "kzt")
-        return "dtp";
-    if (tag == "lii")
-        return "raq";
-    if (tag == "lmm")
-        return "rmx";
-    if (tag == "meg")
-        return "cir";
-    if (tag == "mo")
-        return "ro";
-    if (tag == "mst")
-        return "mry";
-    if (tag == "mwj")
-        return "vaj";
-    if (tag == "myt")
-        return "mry";
-    if (tag == "nad")
-        return "xny";
-    if (tag == "ncp")
-        return "kdz";
-    if (tag == "nnx")
-        return "ngv";
-    if (tag == "nts")
-        return "pij";
-    if (tag == "oun")
-        return "vaj";
-    if (tag == "pcr")
-        return "adx";
-    if (tag == "pmc")
-        return "huw";
-    if (tag == "pmu")
-        return "phr";
-    if (tag == "ppa")
-        return "bfy";
-    if (tag == "ppr")
-        return "lcq";
-    if (tag == "pry")
-        return "prt";
-    if (tag == "puz")
-        return "pub";
-    if (tag == "sca")
-        return "hle";
-    if (tag == "skk")
-        return "oyb";
-    if (tag == "tdu")
-        return "dtp";
-    if (tag == "thc")
-        return "tpo";
-    if (tag == "thx")
-        return "oyb";
-    if (tag == "tie")
-        return "ras";
-    if (tag == "tkk")
-        return "twm";
-    if (tag == "tlw")
-        return "weo";
-    if (tag == "tmp")
-        return "tyj";
-    if (tag == "tne")
-        return "kak";
-    if (tag == "tnf")
-        return "prs";
-    if (tag == "tsf")
-        return "taj";
-    if (tag == "uok")
-        return "ema";
-    if (tag == "xba")
-        return "cax";
-    if (tag == "xia")
-        return "acn";
-    if (tag == "xkh")
-        return "waw";
-    if (tag == "xsj")
-        return "suj";
-    if (tag == "ybd")
-        return "rki";
-    if (tag == "yma")
-        return "lrr";
-    if (tag == "ymt")
-        return "mtm";
-    if (tag == "yos")
-        return "zom";
-    if (tag == "yuu")
-        return "yug";
-    return "";
-}
-
-static std::string intlRedundantLanguageTag(const std::string& tag)
-{
-    // 24 possible replacements
-    if (tag == "hy-arevela")
-        return "hy";
-    if (tag == "hy-arevmda")
-        return "hyw";
-    if (tag == "ja-Latn-hepburn-heploc")
-        return "ja-Latn-alalc97";
-    if (tag == "sgn-BR")
-        return "bzs";
-    if (tag == "sgn-CO")
-        return "csn";
-    if (tag == "sgn-DE")
-        return "gsg";
-    if (tag == "sgn-DK")
-        return "dsl";
-    if (tag == "sgn-ES")
-        return "ssp";
-    if (tag == "sgn-FR")
-        return "fsl";
-    if (tag == "sgn-GB")
-        return "bfi";
-    if (tag == "gss")
-        return "sgn-GR";
-    if (tag == "sgn-IE")
-        return "isg";
-    if (tag == "sgn-IT")
-        return "ise";
-    if (tag == "sgn-JP")
-        return "jsl";
-    if (tag == "sgn-MX")
-        return "mfs";
-    if (tag == "sgn-NI")
-        return "ncs";
-    if (tag == "sgn-NL")
-        return "dse";
-    if (tag == "sgn-NO")
-        return "nsl";
-    if (tag == "sgn-PT")
-        return "psr";
-    if (tag == "sgn-SE")
-        return "swl";
-    if (tag == "sgn-US")
-        return "ase";
-    if (tag == "sgn-ZA")
-        return "sfs";
-    if (tag == "zh-cmn-Hans")
-        return "cmn-Hans";
-    if (tag == "zh-cmn-Hant")
-        return "cmn-Hant";
-    return "";
-}
-
-std::string Intl::preferredLanguage(const std::string& language)
-{
-    auto preferred = intlPreferredLanguageTag(language);
-    if (preferred != "") {
-        return preferred;
-    }
-    return language;
-}
-
-static std::string intlPreferredExtlangTag(const std::string& tag)
-{
-    // 235 possible replacements
-    if (tag == "aao")
-        return "ar";
-    if (tag == "abh")
-        return "ar";
-    if (tag == "abv")
-        return "ar";
-    if (tag == "acm")
-        return "ar";
-    if (tag == "acq")
-        return "ar";
-    if (tag == "acw")
-        return "ar";
-    if (tag == "acx")
-        return "ar";
-    if (tag == "acy")
-        return "ar";
-    if (tag == "adf")
-        return "ar";
-    if (tag == "ads")
-        return "sgn";
-    if (tag == "aeb")
-        return "ar";
-    if (tag == "aec")
-        return "ar";
-    if (tag == "aed")
-        return "sgn";
-    if (tag == "aen")
-        return "sgn";
-    if (tag == "afb")
-        return "ar";
-    if (tag == "afg")
-        return "sgn";
-    if (tag == "ajp")
-        return "ar";
-    if (tag == "apc")
-        return "ar";
-    if (tag == "apd")
-        return "ar";
-    if (tag == "arb")
-        return "ar";
-    if (tag == "arq")
-        return "ar";
-    if (tag == "ars")
-        return "ar";
-    if (tag == "ary")
-        return "ar";
-    if (tag == "arz")
-        return "ar";
-    if (tag == "ase")
-        return "sgn";
-    if (tag == "asf")
-        return "sgn";
-    if (tag == "asp")
-        return "sgn";
-    if (tag == "asq")
-        return "sgn";
-    if (tag == "asw")
-        return "sgn";
-    if (tag == "auz")
-        return "ar";
-    if (tag == "avl")
-        return "ar";
-    if (tag == "ayh")
-        return "ar";
-    if (tag == "ayl")
-        return "ar";
-    if (tag == "ayn")
-        return "ar";
-    if (tag == "ayp")
-        return "ar";
-    if (tag == "bbz")
-        return "ar";
-    if (tag == "bfi")
-        return "sgn";
-    if (tag == "bfk")
-        return "sgn";
-    if (tag == "bjn")
-        return "ms";
-    if (tag == "bog")
-        return "sgn";
-    if (tag == "bqn")
-        return "sgn";
-    if (tag == "bqy")
-        return "sgn";
-    if (tag == "btj")
-        return "ms";
-    if (tag == "bve")
-        return "ms";
-    if (tag == "bvl")
-        return "sgn";
-    if (tag == "bvu")
-        return "ms";
-    if (tag == "bzs")
-        return "sgn";
-    if (tag == "cdo")
-        return "zh";
-    if (tag == "cds")
-        return "sgn";
-    if (tag == "cjy")
-        return "zh";
-    if (tag == "cmn")
-        return "zh";
-    if (tag == "coa")
-        return "ms";
-    if (tag == "cpx")
-        return "zh";
-    if (tag == "csc")
-        return "sgn";
-    if (tag == "csd")
-        return "sgn";
-    if (tag == "cse")
-        return "sgn";
-    if (tag == "csf")
-        return "sgn";
-    if (tag == "csg")
-        return "sgn";
-    if (tag == "csl")
-        return "sgn";
-    if (tag == "csn")
-        return "sgn";
-    if (tag == "csq")
-        return "sgn";
-    if (tag == "csr")
-        return "sgn";
-    if (tag == "czh")
-        return "zh";
-    if (tag == "czo")
-        return "zh";
-    if (tag == "doq")
-        return "sgn";
-    if (tag == "dse")
-        return "sgn";
-    if (tag == "dsl")
-        return "sgn";
-    if (tag == "dup")
-        return "ms";
-    if (tag == "ecs")
-        return "sgn";
-    if (tag == "esl")
-        return "sgn";
-    if (tag == "esn")
-        return "sgn";
-    if (tag == "eso")
-        return "sgn";
-    if (tag == "eth")
-        return "sgn";
-    if (tag == "fcs")
-        return "sgn";
-    if (tag == "fse")
-        return "sgn";
-    if (tag == "fsl")
-        return "sgn";
-    if (tag == "fss")
-        return "sgn";
-    if (tag == "gan")
-        return "zh";
-    if (tag == "gds")
-        return "sgn";
-    if (tag == "gom")
-        return "kok";
-    if (tag == "gse")
-        return "sgn";
-    if (tag == "gsg")
-        return "sgn";
-    if (tag == "gsm")
-        return "sgn";
-    if (tag == "gss")
-        return "sgn";
-    if (tag == "gus")
-        return "sgn";
-    if (tag == "hab")
-        return "sgn";
-    if (tag == "haf")
-        return "sgn";
-    if (tag == "hak")
-        return "zh";
-    if (tag == "hds")
-        return "sgn";
-    if (tag == "hji")
-        return "ms";
-    if (tag == "hks")
-        return "sgn";
-    if (tag == "hos")
-        return "sgn";
-    if (tag == "hps")
-        return "sgn";
-    if (tag == "hsh")
-        return "sgn";
-    if (tag == "hsl")
-        return "sgn";
-    if (tag == "hsn")
-        return "zh";
-    if (tag == "icl")
-        return "sgn";
-    if (tag == "iks")
-        return "sgn";
-    if (tag == "ils")
-        return "sgn";
-    if (tag == "inl")
-        return "sgn";
-    if (tag == "ins")
-        return "sgn";
-    if (tag == "ise")
-        return "sgn";
-    if (tag == "isg")
-        return "sgn";
-    if (tag == "isr")
-        return "sgn";
-    if (tag == "jak")
-        return "ms";
-    if (tag == "jax")
-        return "ms";
-    if (tag == "jcs")
-        return "sgn";
-    if (tag == "jhs")
-        return "sgn";
-    if (tag == "jls")
-        return "sgn";
-    if (tag == "jos")
-        return "sgn";
-    if (tag == "jsl")
-        return "sgn";
-    if (tag == "jus")
-        return "sgn";
-    if (tag == "kgi")
-        return "sgn";
-    if (tag == "knn")
-        return "kok";
-    if (tag == "kvb")
-        return "ms";
-    if (tag == "kvk")
-        return "sgn";
-    if (tag == "kvr")
-        return "ms";
-    if (tag == "kxd")
-        return "ms";
-    if (tag == "lbs")
-        return "sgn";
-    if (tag == "lce")
-        return "ms";
-    if (tag == "lcf")
-        return "ms";
-    if (tag == "liw")
-        return "ms";
-    if (tag == "lls")
-        return "sgn";
-    if (tag == "lsg")
-        return "sgn";
-    if (tag == "lsl")
-        return "sgn";
-    if (tag == "lso")
-        return "sgn";
-    if (tag == "lsp")
-        return "sgn";
-    if (tag == "lst")
-        return "sgn";
-    if (tag == "lsy")
-        return "sgn";
-    if (tag == "ltg")
-        return "lv";
-    if (tag == "lvs")
-        return "lv";
-    if (tag == "lws")
-        return "sgn";
-    if (tag == "lzh")
-        return "zh";
-    if (tag == "max")
-        return "ms";
-    if (tag == "mdl")
-        return "sgn";
-    if (tag == "meo")
-        return "ms";
-    if (tag == "mfa")
-        return "ms";
-    if (tag == "mfb")
-        return "ms";
-    if (tag == "mfs")
-        return "sgn";
-    if (tag == "min")
-        return "ms";
-    if (tag == "mnp")
-        return "zh";
-    if (tag == "mqg")
-        return "ms";
-    if (tag == "mre")
-        return "sgn";
-    if (tag == "msd")
-        return "sgn";
-    if (tag == "msi")
-        return "ms";
-    if (tag == "msr")
-        return "sgn";
-    if (tag == "mui")
-        return "ms";
-    if (tag == "mzc")
-        return "sgn";
-    if (tag == "mzg")
-        return "sgn";
-    if (tag == "mzy")
-        return "sgn";
-    if (tag == "nan")
-        return "zh";
-    if (tag == "nbs")
-        return "sgn";
-    if (tag == "ncs")
-        return "sgn";
-    if (tag == "nsi")
-        return "sgn";
-    if (tag == "nsl")
-        return "sgn";
-    if (tag == "nsp")
-        return "sgn";
-    if (tag == "nsr")
-        return "sgn";
-    if (tag == "nzs")
-        return "sgn";
-    if (tag == "okl")
-        return "sgn";
-    if (tag == "orn")
-        return "ms";
-    if (tag == "ors")
-        return "ms";
-    if (tag == "pel")
-        return "ms";
-    if (tag == "pga")
-        return "ar";
-    if (tag == "pgz")
-        return "sgn";
-    if (tag == "pks")
-        return "sgn";
-    if (tag == "prl")
-        return "sgn";
-    if (tag == "prz")
-        return "sgn";
-    if (tag == "psc")
-        return "sgn";
-    if (tag == "psd")
-        return "sgn";
-    if (tag == "pse")
-        return "ms";
-    if (tag == "psg")
-        return "sgn";
-    if (tag == "psl")
-        return "sgn";
-    if (tag == "pso")
-        return "sgn";
-    if (tag == "psp")
-        return "sgn";
-    if (tag == "psr")
-        return "sgn";
-    if (tag == "pys")
-        return "sgn";
-    if (tag == "rms")
-        return "sgn";
-    if (tag == "rsi")
-        return "sgn";
-    if (tag == "rsl")
-        return "sgn";
-    if (tag == "rsm")
-        return "sgn";
-    if (tag == "sdl")
-        return "sgn";
-    if (tag == "sfb")
-        return "sgn";
-    if (tag == "sfs")
-        return "sgn";
-    if (tag == "sgg")
-        return "sgn";
-    if (tag == "sgx")
-        return "sgn";
-    if (tag == "shu")
-        return "ar";
-    if (tag == "slf")
-        return "sgn";
-    if (tag == "sls")
-        return "sgn";
-    if (tag == "sqk")
-        return "sgn";
-    if (tag == "sqs")
-        return "sgn";
-    if (tag == "ssh")
-        return "ar";
-    if (tag == "ssp")
-        return "sgn";
-    if (tag == "ssr")
-        return "sgn";
-    if (tag == "svk")
-        return "sgn";
-    if (tag == "swc")
-        return "sw";
-    if (tag == "swh")
-        return "sw";
-    if (tag == "swl")
-        return "sgn";
-    if (tag == "syy")
-        return "sgn";
-    if (tag == "szs")
-        return "sgn";
-    if (tag == "tmw")
-        return "ms";
-    if (tag == "tse")
-        return "sgn";
-    if (tag == "tsm")
-        return "sgn";
-    if (tag == "tsq")
-        return "sgn";
-    if (tag == "tss")
-        return "sgn";
-    if (tag == "tsy")
-        return "sgn";
-    if (tag == "tza")
-        return "sgn";
-    if (tag == "ugn")
-        return "sgn";
-    if (tag == "ugy")
-        return "sgn";
-    if (tag == "ukl")
-        return "sgn";
-    if (tag == "uks")
-        return "sgn";
-    if (tag == "urk")
-        return "ms";
-    if (tag == "uzn")
-        return "uz";
-    if (tag == "uzs")
-        return "uz";
-    if (tag == "vgt")
-        return "sgn";
-    if (tag == "vkk")
-        return "ms";
-    if (tag == "vkt")
-        return "ms";
-    if (tag == "vsi")
-        return "sgn";
-    if (tag == "vsl")
-        return "sgn";
-    if (tag == "vsv")
-        return "sgn";
-    if (tag == "wbs")
-        return "sgn";
-    if (tag == "wuu")
-        return "zh";
-    if (tag == "xki")
-        return "sgn";
-    if (tag == "xml")
-        return "sgn";
-    if (tag == "xmm")
-        return "ms";
-    if (tag == "xms")
-        return "sgn";
-    if (tag == "yds")
-        return "sgn";
-    if (tag == "ygs")
-        return "sgn";
-    if (tag == "yhs")
-        return "sgn";
-    if (tag == "ysl")
-        return "sgn";
-    if (tag == "yue")
-        return "zh";
-    if (tag == "zib")
-        return "sgn";
-    if (tag == "zlm")
-        return "ms";
-    if (tag == "zmi")
-        return "ms";
-    if (tag == "zsl")
-        return "sgn";
-    if (tag == "zsm")
-        return "ms";
-    return "";
-}
-
-static std::string intlPreferredRegionTag(const std::string& tag)
-{
-    // 6 possible replacements
-    if (tag == "BU")
-        return "MM";
-    if (tag == "DD")
-        return "DE";
-    if (tag == "FX")
-        return "FR";
-    if (tag == "TP")
-        return "TL";
-    if (tag == "YD")
-        return "YE";
-    if (tag == "ZR")
-        return "CD";
-    return "";
-}
-
-static std::string preferredRegion(const std::string& region)
-{
-    auto preferred = intlPreferredRegionTag(region);
-    if (preferred != "") {
-        return preferred;
-    }
-    return region;
-}
-
-static std::string privateUseLangTag(const std::vector<std::string>& parts, size_t startIndex)
-{
-    size_t numParts = parts.size();
-    size_t currentIndex = startIndex;
-
-    // Check for privateuse.
-    // privateuse = "x" 1*("-" (2*8alphanum))
-    StringBuilder privateuse;
-    while (currentIndex < numParts) {
-        std::string singleton = parts[currentIndex];
-        unsigned singletonLength = singleton.length();
-        bool isValid = (singletonLength == 1 && (singleton == "x" || singleton == "X"));
-        if (!isValid)
-            break;
-
-        if (currentIndex != startIndex)
-            privateuse.appendChar('-');
-
-        ++currentIndex;
-        unsigned numExtParts = 0;
-        privateuse.appendChar('x');
-        while (currentIndex < numParts) {
-            std::string extPart = parts[currentIndex];
-            unsigned extPartLength = extPart.length();
-
-            bool isValid = (extPartLength >= 1 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
-            if (!isValid)
-                break;
-
-            ++currentIndex;
-            ++numExtParts;
-            privateuse.appendChar('-');
-            std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
-            privateuse.appendString(String::fromUTF8(extPart.data(), extPart.length()));
-        }
-
-        // Requires at least one production.
-        if (!numExtParts)
-            return std::string();
-    }
-
-    // Leftovers makes it invalid.
-    if (currentIndex < numParts)
-        return std::string();
-
-    return privateuse.finalize()->toNonGCUTF8StringData();
-}
-
-Intl::CanonicalizedLangunageTag Intl::canonicalizeLanguageTag(const std::string& locale, const std::string& unicodeExtensionNameShouldIgnored)
-{
-    std::vector<std::string> parts = split(locale, '-');
-
-    Intl::CanonicalizedLangunageTag result;
-
-    // Follows the grammar at https://www.rfc-editor.org/rfc/bcp/bcp47.txt
-    // langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]
-    size_t numParts = parts.size();
-    // Check for language.
-    // language = 2*3ALPHA ["-" extlang] / 4ALPHA (reserved) / 5*8ALPHA
-    size_t currentIndex = 0;
-    std::string language = parts[currentIndex];
-    unsigned languageLength = language.length();
-    bool canHaveExtlang = languageLength >= 2 && languageLength <= 3;
-    bool isValidLanguage = languageLength != 4 && languageLength >= 2 && languageLength <= 8 && isAllSpecialCharacters(language, isASCIIAlpha);
-    if (!isValidLanguage) {
-        return Intl::CanonicalizedLangunageTag();
-    }
-
-    ++currentIndex;
-    StringBuilder canonical;
-
-    std::transform(language.begin(), language.end(), language.begin(), tolower);
-    result.language = language;
-    language = Intl::preferredLanguage(language);
-    canonical.appendString(String::fromUTF8(language.data(), language.length()));
-
-    // Check for extlang.
-    // extlang = 3ALPHA *2("-" 3ALPHA)
-    if (canHaveExtlang) {
-        for (unsigned times = 0; times < 3 && currentIndex < numParts; ++times) {
-            std::string extlang = parts[currentIndex];
-            unsigned extlangLength = extlang.length();
-            if (extlangLength == 3 && isAllSpecialCharacters(extlang, isASCIIAlpha)) {
-                ++currentIndex;
-                std::transform(extlang.begin(), extlang.end(), extlang.begin(), tolower);
-                result.extLang.push_back(extlang);
-                if (!times && intlPreferredExtlangTag(extlang) == language) {
-                    canonical.clear();
-                    canonical.appendString(String::fromUTF8(extlang.data(), extlang.length()));
-                    continue;
-                }
-                canonical.appendString("-");
-                canonical.appendString(String::fromUTF8(extlang.data(), extlang.length()));
-            } else {
-                break;
-            }
-        }
-    }
-
-    // Check for script.
-    // script = 4ALPHA
-    if (currentIndex < numParts) {
-        std::string script = parts[currentIndex];
-        unsigned scriptLength = script.length();
-        if (scriptLength == 4 && isAllSpecialCharacters(script, isASCIIAlpha)) {
-            ++currentIndex;
-            canonical.appendString("-");
-            std::transform(script.begin(), script.end(), script.begin(), tolower);
-            result.script += (char)toupper(script[0]);
-            canonical.appendChar((char)toupper(script[0]));
-            script = script.substr(1, 3);
-            result.script += script;
-            canonical.appendString(String::fromUTF8(script.data(), script.length()));
-        }
-    }
-
-    // Check for region.
-    // region = 2ALPHA / 3DIGIT
-    if (currentIndex < numParts) {
-        std::string region = parts[currentIndex];
-        unsigned regionLength = region.length();
-        bool isValidRegion = ((regionLength == 2 && isAllSpecialCharacters(region, isASCIIAlpha))
-                              || (regionLength == 3 && isAllSpecialCharacters(region, isASCIIDigit)));
-        if (isValidRegion) {
-            ++currentIndex;
-            canonical.appendChar('-');
-            std::transform(region.begin(), region.end(), region.begin(), toupper);
-            result.region = region;
-            auto preffered = preferredRegion(region);
-            canonical.appendString(String::fromUTF8(preffered.data(), preffered.length()));
-        }
-    }
-
-    // Check for variant.
-    // variant = 5*8alphanum / (DIGIT 3alphanum)
-    std::unordered_set<std::string> subtags;
-    while (currentIndex < numParts) {
-        std::string variant = parts[currentIndex];
-        unsigned variantLength = variant.length();
-        bool isValidVariant = ((variantLength >= 5 && variantLength <= 8 && isAllSpecialCharacters(variant, isASCIIAlphanumeric))
-                               || (variantLength == 4 && isASCIIDigit(variant[0]) && isAllSpecialCharacters(variant.substr(1, 3), isASCIIAlphanumeric)));
-        if (!isValidVariant) {
-            break;
-        }
-
-        // Cannot include duplicate subtags (case insensitive).
-        std::string lowerVariant = variant;
-        std::transform(lowerVariant.begin(), lowerVariant.end(), lowerVariant.begin(), tolower);
-        auto iter = subtags.find(lowerVariant);
-        if (iter != subtags.end()) {
-            return Intl::CanonicalizedLangunageTag();
-        }
-        subtags.insert(lowerVariant);
-
-        ++currentIndex;
-
-        result.variant.push_back(lowerVariant);
-    }
-
-    std::sort(result.variant.begin(), result.variant.end());
-    for (size_t i = 0; i < result.variant.size(); i++) {
-        canonical.appendChar('-');
-        canonical.appendString(result.variant[i].data());
-    }
-
-    // Check for extension.
-    // extension = singleton 1*("-" (2*8alphanum))
-    // singleton = alphanum except x or X
-    subtags.clear();
-    while (currentIndex < numParts) {
-        std::string possibleSingleton = parts[currentIndex];
-        unsigned singletonLength = possibleSingleton.length();
-        bool isValidSingleton = (singletonLength == 1 && possibleSingleton != "x" && possibleSingleton != "X" && isASCIIAlphanumeric(possibleSingleton[0]));
-        if (!isValidSingleton) {
-            break;
-        }
-
-        // Cannot include duplicate singleton (case insensitive).
-        std::string singleton = possibleSingleton;
-        std::transform(possibleSingleton.begin(), possibleSingleton.end(), possibleSingleton.begin(), tolower);
-
-        auto iter = subtags.find(singleton);
-        if (iter != subtags.end()) {
-            return Intl::CanonicalizedLangunageTag();
-        }
-        subtags.insert(singleton);
-
-        Intl::CanonicalizedLangunageTag::ExtensionSingleton singletonValue;
-        singletonValue.key = possibleSingleton[0];
-
-        ++currentIndex;
-
-        bool unicodeExtensionIgnored = false;
-        if (singletonValue.key == 'u') {
-            // "u" needs ordered key, value
-            // "u" doesn't allow single "true" as value
-
-            std::vector<std::pair<std::string, std::vector<std::string>>> values;
-
-            std::string key;
-            std::vector<std::string> value;
-
-            while (currentIndex < numParts) {
-                std::string extPart = parts[currentIndex];
-                unsigned extPartLength = extPart.length();
-
-                bool isValid = (extPartLength >= 2 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
-                if (!isValid) {
-                    break;
-                }
-
-                ++currentIndex;
-                std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
-
-                if (extPartLength == 2) {
-                    if (key.length() || value.size()) {
-                        if (key.length() && value.size() == 1 && value[0] == "true") {
-                            value.clear();
-                        }
-                        values.push_back(std::make_pair(key, value));
-                        key.clear();
-                        value.clear();
-                    }
-                    key = extPart;
-                } else {
-                    value.push_back(extPart);
-                }
-            }
-
-            bool unicodeExtensionIgnoredOnce = (key.length() && key == unicodeExtensionNameShouldIgnored);
-            unicodeExtensionIgnored |= unicodeExtensionIgnoredOnce;
-
-            if (!unicodeExtensionIgnoredOnce && (key.length() || value.size())) {
-                if (key.length() && value.size() == 1 && value[0] == "true") {
-                    value.clear();
-                }
-                values.push_back(std::make_pair(key, value));
-                key.clear();
-                value.clear();
-            }
-
-            std::sort(values.begin(), values.end(),
-                      [](const std::pair<std::string, std::vector<std::string>>& a, const std::pair<std::string, std::vector<std::string>>& b) -> bool {
-                          return a.first < b.first;
-                      });
-
-            // Attributes in Unicode extensions are reordered in US-ASCII order.
-            if (values.size() && !values.begin()->first.length()) {
-                std::sort(values.begin()->second.begin(), values.begin()->second.end());
-            }
-
-            std::string resultValue;
-            for (size_t i = 0; i < values.size(); i++) {
-                if (values[i].first.size()) {
-                    if (resultValue.size()) {
-                        resultValue += '-';
-                    }
-                    resultValue += values[i].first;
-                }
-
-                for (size_t j = 0; j < values[i].second.size(); j++) {
-                    if (resultValue.size()) {
-                        resultValue += '-';
-                    }
-                    resultValue += values[i].second[j];
-                }
-            }
-
-            singletonValue.value = std::move(resultValue);
-
-            std::vector<std::pair<std::string, std::string>> unicodeExtensionValue;
-
-            for (size_t i = 0; i < values.size(); i++) {
-                std::string singleUnicodeExtensionValue;
-                for (size_t j = 0; j < values[i].second.size(); j++) {
-                    if (singleUnicodeExtensionValue.length()) {
-                        singleUnicodeExtensionValue += '-';
-                    }
-                    singleUnicodeExtensionValue += values[i].second[j];
-                }
-                unicodeExtensionValue.push_back(std::make_pair(values[i].first, singleUnicodeExtensionValue));
-            }
-
-            result.unicodeExtension = std::move(unicodeExtensionValue);
-
-            if (unicodeExtensionIgnored && !result.unicodeExtension.size()) {
-                continue;
-            }
-        } else {
-            std::string single;
-            while (currentIndex < numParts) {
-                std::string extPart = parts[currentIndex];
-                unsigned extPartLength = extPart.length();
-
-                bool isValid = (extPartLength >= 2 && extPartLength <= 8 && isAllSpecialCharacters(extPart, isASCIIAlphanumeric));
-                if (!isValid) {
-                    break;
-                }
-
-                ++currentIndex;
-                std::transform(extPart.begin(), extPart.end(), extPart.begin(), tolower);
-
-                if (single.length()) {
-                    single += '-';
-                }
-                single += extPart;
-            }
-
-            singletonValue.value = std::move(single);
-        }
-
-        result.extensions.push_back(singletonValue);
-
-        // Requires at least one production.
-        if (!result.extensions.back().value.size()) {
-            return Intl::CanonicalizedLangunageTag();
-        }
-    }
-
-    // Add extensions to canonical sorted by singleton.
-    std::sort(result.extensions.begin(), result.extensions.end(),
-              [](const Intl::CanonicalizedLangunageTag::ExtensionSingleton& a, const Intl::CanonicalizedLangunageTag::ExtensionSingleton& b) -> bool {
-                  return a.key < b.key;
-              });
-    size_t numExtenstions = result.extensions.size();
-    for (size_t i = 0; i < numExtenstions; ++i) {
-        canonical.appendChar('-');
-        canonical.appendChar(result.extensions[i].key);
-        canonical.appendChar('-');
-        canonical.appendString(String::fromUTF8(result.extensions[i].value.data(), result.extensions[i].value.length()));
-    }
-
-    // Check for privateuse.
-    if (currentIndex < numParts) {
-        std::string privateUse = privateUseLangTag(parts, currentIndex);
-        if (privateUse.length() == 0) {
-            return Intl::CanonicalizedLangunageTag();
-        }
-        canonical.appendChar('-');
-        canonical.appendString(String::fromUTF8(privateUse.data(), privateUse.length()));
-        result.privateUse = privateUse;
-    }
-
-    String* e = canonical.finalize();
-    auto estd = e->toNonGCUTF8StringData();
-    auto preferred = intlRedundantLanguageTag(estd);
-    if (preferred != "") {
-        e = String::fromUTF8(preferred.data(), preferred.length());
-    }
-
-    result.canonicalizedTag = e;
-    return result;
-}
-
-Intl::CanonicalizedLangunageTag Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(const std::string& locale)
-{
-    if (isValidTagInBCP47ButInvalidOnUTS35(locale)) {
-        return Intl::CanonicalizedLangunageTag();
-    }
-    std::string grandfather = grandfatheredLangTag(locale);
-    if (grandfather.length()) {
-        return canonicalizeLanguageTag(grandfather);
-    }
-
-    return canonicalizeLanguageTag(locale);
-}
-
-String* Intl::icuLocaleToBCP47Tag(String* string)
-{
-    StringBuilder sb;
-    for (size_t i = 0; i < string->length(); i++) {
-        char16_t ch = string->charAt(i);
-        if (ch == '_')
-            ch = '-';
-        sb.appendChar(ch);
-    }
-    return sb.finalize();
-}
-
-static String* defaultLocale(ExecutionState& state)
-{
-    String* localeString = String::fromUTF8(state.context()->vmInstance()->locale().data(), state.context()->vmInstance()->locale().length());
-    return Intl::icuLocaleToBCP47Tag(localeString);
-}
-
-static String* removeUnicodeLocaleExtension(ExecutionState& state, String* locale)
-{
-    auto utf8 = locale->toUTF8StringData();
-    std::string stdUTF8(utf8.data(), utf8.length());
-    std::vector<std::string> parts = split(stdUTF8, '-');
-
-    StringBuilder builder;
-    size_t partsSize = parts.size();
-    if (partsSize > 0)
-        builder.appendString(String::fromUTF8(parts[0].data(), parts[0].size()));
-    for (size_t p = 1; p < partsSize; ++p) {
-        if (parts[p] == "u") {
-            // Skip the u- and anything that follows until another singleton.
-            // While the next part is part of the unicode extension, skip it.
-            while (p + 1 < partsSize && parts[p + 1].length() > 1)
-                ++p;
-        } else {
-            builder.appendChar('-');
-            builder.appendString(String::fromUTF8(parts[p].data(), parts[p].size()));
-        }
-    }
-    return builder.finalize();
-}
-
-ValueVector Intl::canonicalizeLocaleList(ExecutionState& state, Value locales)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.1
-    // If locales is undefined, then
-    if (locales.isUndefined()) {
-        // Return a new empty List.
-        return ValueVector();
-    }
-    // Let seen be a new empty List.
-    ValueVector seen;
-
-    Object* O;
-    // If Type(locales) is String or locales has an [[InitializedLocale]] internal slot, then
-    if (locales.isString() || (locales.isObject() && locales.asObject()->isIntlLocaleObject())) {
-        // Let O be CreateArrayFromList(« locales »).
-        ValueVector vv;
-        vv.push_back(locales);
-        O = Object::createArrayFromList(state, vv);
-    } else {
-        // Else
-        // Let O be ToObject(locales).
-        O = locales.toObject(state);
-    }
-
-    uint64_t len = O->length(state);
-    // Let k be 0.
-    // Repeat, while k < len
-    uint64_t k = 0;
-    while (k < len) {
-        // Let Pk be ToString(k).
-        ObjectPropertyName pk(state, Value(k));
-        ObjectHasPropertyResult pkResult = O->hasProperty(state, pk);
-        // Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
-        // If kPresent is true, then
-        if (pkResult.hasProperty()) {
-            // Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
-            Value kValue = pkResult.value(state, pk, O);
-            // If the type of kValue is not String or Object, then throw a TypeError exception.
-            if (!kValue.isString() && !kValue.isObject()) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Type of element of locales must be String or Object");
-            }
-
-            String* tag;
-            // If Type(kValue) is Object and kValue has an [[InitializedLocale]] internal slot, then
-            if (kValue.isObject() && kValue.asObject()->isIntlLocaleObject()) {
-                // Let tag be kValue.[[Locale]].
-                tag = kValue.asObject()->asIntlLocaleObject()->locale();
-            } else {
-                // Else,
-                // Let tag be ToString(kValue).
-                tag = kValue.toString(state);
-            }
-            // If the result of calling the abstract operation IsStructurallyValidLanguageTag (defined in 6.2.2), passing tag as the argument,
-            // is false, then throw a RangeError exception.
-            // Let tag be the result of calling the abstract operation CanonicalizeLanguageTag (defined in 6.2.3), passing tag as the argument.
-            // If tag is not an element of seen, then append tag as the last element of seen.
-            auto canonicalizedTag = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(tag->toNonGCUTF8StringData());
-            if (!canonicalizedTag.canonicalizedTag) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got Invalid locale");
-            }
-            tag = canonicalizedTag.canonicalizedTag.value();
-            bool has = false;
-            for (size_t i = 0; i < seen.size(); i++) {
-                if (seen[i].equalsTo(state, tag)) {
-                    has = true;
-                    break;
-                }
-            }
-            if (!has) {
-                seen.pushBack(tag);
-            }
-
-            // Increase k by 1.
-            k++;
-        } else {
-            // Increase k by 1.
-            int64_t nextIndex;
-            Object::nextIndexForward(state, O, k, len, nextIndex);
-            k = nextIndex;
-        }
-    }
-
-    // Return seen.
-    return seen;
-}
-
-static String* bestAvailableLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, Value locale)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.2
-    // Let candidate be locale.
-    String* candidate = locale.toString(state);
-
-    // Repeat
-    while (candidate->length()) {
-        // If availableLocales contains an element equal to candidate, then return candidate.
-        bool contains = false;
-        for (size_t i = 0; i < availableLocales.size(); i++) {
-            if (availableLocales[i]->equals(candidate)) {
-                contains = true;
-                break;
-            }
-        }
-
-        if (contains)
-            return candidate;
-
-        // Let pos be the character index of the last occurrence of "-" (U+002D) within candidate. If that character does not occur, return undefined.
-        size_t pos = candidate->rfind(state.context()->staticStrings().asciiTable[(size_t)'-'].string(), candidate->length() - 1);
-        if (pos == SIZE_MAX)
-            return String::emptyString;
-
-        // If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, then decrease pos by 2.
-        if (pos >= 2 && candidate->charAt(pos - 2) == '-')
-            pos -= 2;
-
-        // d. Let candidate be the substring of candidate from position 0, inclusive, to position pos, exclusive.
-        candidate = candidate->substring(0, pos);
-    }
-
-    return String::emptyString;
-}
-
-static Intl::IntlMatcherResult lookupMatcher(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>> availableLocales, const ValueVector& requestedLocales)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.3
-    // Let i be 0.
-    size_t i = 0;
-    // Let len be the number of elements in requestedLocales.
-    size_t len = requestedLocales.size();
-    // Let availableLocale be undefined.
-    String* availableLocale = String::emptyString;
-
-    String* locale = String::emptyString;
-    String* noExtensionsLocale = String::emptyString;
-
-    // Repeat while i < len and availableLocale is undefined:
-    while (i < len && availableLocale->length() == 0) {
-        // Let locale be the element of requestedLocales at 0-origined list position i.
-        locale = requestedLocales[i].toString(state);
-        // Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
-        noExtensionsLocale = removeUnicodeLocaleExtension(state, locale);
-        // Let availableLocale be the result of calling the BestAvailableLocale abstract operation (defined in 9.2.2) with arguments availableLocales and noExtensionsLocale.
-        availableLocale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
-        // Increase i by 1.
-        i++;
-    }
-
-    // Let result be a new Record.
-    Intl::IntlMatcherResult result;
-
-    // If availableLocale is not undefined, then
-    if (availableLocale->length()) {
-        // Set result.[[locale]] to availableLocale.
-        result.locale = availableLocale;
-        // If locale and noExtensionsLocale are not the same String value, then
-        if (!locale->equals(noExtensionsLocale)) {
-            // Let extension be the String value consisting of the first substring of locale that is a Unicode locale extension sequence.
-            // Let extensionIndex be the character position of the initial "-" of the first Unicode locale extension sequence within locale.
-            // Set result.[[extension]] to extension.
-            // Set result.[[extensionIndex]] to extensionIndex.
-
-            bool unicodeExtensionExists = false;
-            if (locale->find("-x-") != SIZE_MAX) {
-                unicodeExtensionExists = true;
-            }
-
-            if (!unicodeExtensionExists) {
-                size_t extensionIndex = locale->find("-u-");
-                ASSERT(extensionIndex != SIZE_MAX);
-
-                size_t extensionLength = locale->length() - extensionIndex;
-                size_t end = extensionIndex + 3;
-                while (end < locale->length()) {
-                    end = locale->find("-", end);
-                    if (end == SIZE_MAX)
-                        break;
-                    if (end + 2 < locale->length() && locale->charAt(end + 2) == '-') {
-                        extensionLength = end - extensionIndex;
-                        break;
-                    }
-                    end++;
-                }
-                result.extension = locale->substring(extensionIndex, extensionIndex + extensionLength);
-                result.extensionIndex = extensionIndex;
-            }
-        }
-    } else {
-        // Set result.[[locale]] to the value returned by the DefaultLocale abstract operation (defined in 6.2.4).
-        result.locale = defaultLocale(state);
-    }
-
-    return result;
-}
-
-static Intl::IntlMatcherResult bestFitMatcher(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>> availableLocales, const ValueVector& requestedLocales)
-{
-    // TODO
-    return lookupMatcher(state, availableLocales, requestedLocales);
-}
-
-static Optional<String*> unicodeExtensionValue(ExecutionState& state, String* extension, const char* key)
-{
-    // Let size be the number of elements in extension.
-    auto size = extension->length();
-    // Let searchValue be the concatenation of "-", key, and "-".
-    StringBuilder searchValueBuilder;
-    searchValueBuilder.appendChar('-');
-    searchValueBuilder.appendString(key);
-    searchValueBuilder.appendChar('-');
-    String* searchValue = searchValueBuilder.finalize();
-
-    // Let pos be Call(%StringProto_indexOf%, extension, « searchValue »).
-    size_t pos = extension->find(searchValue);
-
-    // If pos ≠ -1, then
-    if (pos != SIZE_MAX) {
-        // Let start be pos + 4.
-        size_t start = pos + 4;
-        // Let end be start.
-        size_t end = start;
-        // Let k be start.
-        size_t k = start;
-        // Let done be false.
-        bool done = false;
-
-        // Repeat, while done is false
-        while (!done) {
-            // Let e be Call(%StringProto_indexOf%, extension, « "-", k »).
-            size_t e = extension->find("-", k);
-            size_t len;
-            // If e = -1,
-            if (e == SIZE_MAX) {
-                // let len be size - k;
-                len = size - k;
-            } else {
-                // else let len be e - k.
-                len = e - k;
-            }
-
-            // If len = 2, then
-            if (len == 2) {
-                // Let done be true.
-                done = true;
-            } else if (e == SIZE_MAX) {
-                // Else if e = -1, then
-                // Let end be size.
-                end = size;
-                // Let done be true.
-                done = true;
-            } else {
-                // Else,
-                // Let end be e.
-                end = e;
-                // Let k be e + 1.
-                k = e + 1;
-            }
-        }
-
-        // Return the String value equal to the substring of extension
-        // consisting of the code units at indices start (inclusive) through end (exclusive).
-        return extension->substring(start, end);
-    }
-
-    // Let searchValue be the concatenation of "-" and key.
-    searchValueBuilder.appendChar('-');
-    searchValueBuilder.appendString(key);
-    searchValue = searchValueBuilder.finalize();
-    // Let pos be Call(%StringProto_indexOf%, extension, « searchValue »).
-    pos = extension->find(searchValue);
-    // If pos ≠ -1 and pos + 3 = size, then
-    if (pos != SIZE_MAX && pos + 3 == size) {
-        return String::emptyString;
-    }
-
-    return nullptr;
-}
-
-
-static bool stringVectorContains(const std::vector<std::string>& v, const std::string& key)
-{
-    for (size_t j = 0; j < v.size(); j++) {
-        if (v[j] == key) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-
-StringMap Intl::resolveLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, const StringMap& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, LocaleDataImplFunction localeData)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-resolvelocale
-
-    // Let matcher be the value of options.[[localeMatcher]].
-    auto iter = options.find("localeMatcher");
-    Value matcher;
-    if (iter != options.end()) {
-        matcher = iter->second;
-    }
-
-    Intl::IntlMatcherResult r;
-    // If matcher is "lookup", then
-    if (matcher.equalsTo(state, state.context()->staticStrings().lazyLookup().string())) {
-        // Let r be LookupMatcher(availableLocales, requestedLocales).
-        r = lookupMatcher(state, availableLocales, requestedLocales);
-    } else {
-        // Else
-        // Let r be BestFitMatcher(availableLocales, requestedLocales).
-        r = bestFitMatcher(state, availableLocales, requestedLocales);
-    }
-
-    // Let foundLocale be the value of r.[[locale]].
-    String* foundLocale = r.locale;
-
-    // Let result be a new Record.
-    StringMap result;
-
-    // Set result.[[dataLocale]] to foundLocale.
-    result.insert(std::make_pair("dataLocale", foundLocale));
-
-    // Let supportedExtension be "-u".
-    String* supportedExtension = state.context()->staticStrings().lazyDashU().string();
-
-    // For each element key of relevantExtensionKeys in List order, do
-    size_t i = 0;
-    size_t len = relevantExtensionKeyCount;
-    while (i < len) {
-        const char* key = relevantExtensionKeys[i];
-        // Let foundLocaleData be localeData.[[<foundLocale>]].
-        // Let keyLocaleData be foundLocaleData.[[<key>]].
-        std::vector<std::string> keyLocaleData = localeData(foundLocale, i);
-        // Let value be keyLocaleData[0].
-        std::string value = keyLocaleData[0];
-
-        // Let supportedExtensionAddition be "".
-        String* supportedExtensionAddition = String::emptyString;
-
-        // If r has an [[extension]] field, then
-        if (r.extension->length()) {
-            // Let requestedValue be UnicodeExtensionValue(r.[[extension]], key).
-            Optional<String*> requestedValue = unicodeExtensionValue(state, r.extension, key);
-
-            // If requestedValue is not undefined, then
-            if (requestedValue) {
-                // If requestedValue is not the empty String, then
-                if (requestedValue.value()->length()) {
-                    // If keyLocaleData contains requestedValue, then
-                    if (stringVectorContains(keyLocaleData, requestedValue.value()->toNonGCUTF8StringData())) {
-                        // Let value be requestedValue.
-                        value = requestedValue.value()->toNonGCUTF8StringData();
-                        // Let supportedExtensionAddition be the concatenation of "-", key, "-", and value.
-                        StringBuilder supportedExtensionAdditionBuilder;
-                        supportedExtensionAdditionBuilder.appendChar('-');
-                        supportedExtensionAdditionBuilder.appendString(key);
-                        supportedExtensionAdditionBuilder.appendChar('-');
-                        supportedExtensionAdditionBuilder.appendString(value.data());
-                        supportedExtensionAddition = supportedExtensionAdditionBuilder.finalize();
-                    }
-                } else if (stringVectorContains(keyLocaleData, "true")) {
-                    // Else if keyLocaleData contains "true", then
-                    // Let value be "true".
-                    value = "true";
-                    // Let supportedExtensionAddition be the concatenation of "-" and key.
-                    StringBuilder supportedExtensionAdditionBuilder;
-                    supportedExtensionAdditionBuilder.appendChar('-');
-                    supportedExtensionAdditionBuilder.appendString(key);
-                    supportedExtensionAddition = supportedExtensionAdditionBuilder.finalize();
-                }
-            }
-        }
-
-        // If options has a field [[<key>]], then
-        if (options.find(key) != options.end()) {
-            // Let optionsValue be options.[[<key>]].
-            auto optionsValue = options.at(key);
-            // Assert: Type(optionsValue) is either String, Undefined, or Null.
-            // If keyLocaleData contains optionsValue, then
-            if (stringVectorContains(keyLocaleData, optionsValue->toNonGCUTF8StringData())) {
-                // If SameValue(optionsValue, value) is false, then
-                if (!optionsValue->equals(value.data(), value.length())) {
-                    // Let value be optionsValue.
-                    value = optionsValue->toNonGCUTF8StringData();
-                    // Let supportedExtensionAddition be "".
-                    supportedExtensionAddition = String::emptyString;
-                }
-            }
-        }
-
-        // Set result.[[<key>]] to value.
-        result.insert(std::make_pair(key, String::fromUTF8(value.data(), value.length())));
-
-        // Append supportedExtensionAddition to supportedExtension.
-        StringBuilder sb;
-        sb.appendString(supportedExtension);
-        sb.appendString(supportedExtensionAddition);
-        supportedExtension = sb.finalize();
-
-        i++;
-    }
-
-    // If the length of supportedExtension is greater than 2, then
-    if (supportedExtension->length() > 2) {
-        // Let privateIndex be Call(%StringProto_indexOf%, foundLocale, « "-x-" »).
-        size_t privateIndex = foundLocale->find("-x-");
-
-        // If privateIndex = -1, then
-        if (privateIndex != SIZE_MAX) {
-            // Let foundLocale be the concatenation of foundLocale and supportedExtension.
-            StringBuilder sb;
-            sb.appendString(foundLocale);
-            sb.appendString(supportedExtension);
-            foundLocale = sb.finalize();
-        } else {
-            size_t len = foundLocale->length();
-            // Let preExtension be the substring of foundLocale from position 0, inclusive, to position extensionIndex, exclusive.
-            String* preExtension = foundLocale->substring(0, len > r.extensionIndex ? r.extensionIndex : len);
-
-            // Let postExtension be the substring of foundLocale from position extensionIndex to the end of the string.
-            String* postExtension = String::emptyString;
-            if (r.extensionIndex < len) {
-                postExtension = foundLocale->substring(r.extensionIndex, len);
-            }
-            // Let foundLocale be the concatenation of preExtension, supportedExtension, and postExtension.
-            StringBuilder sb;
-            sb.appendString(preExtension);
-            sb.appendString(supportedExtension);
-            sb.appendString(postExtension);
-            foundLocale = sb.finalize();
-        }
-
-        // Let foundLocale be CanonicalizeLanguageTag(foundLocale).
-        // Assert: IsStructurallyValidLanguageTag(foundLocale) is true.
-        foundLocale = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(foundLocale->toNonGCUTF8StringData()).canonicalizedTag.value();
-    }
-    // Set result.[[locale]] to foundLocale.
-    result.insert(std::make_pair("locale", foundLocale));
-    // Return result.
-    return result;
-}
-
-
-static ValueVector lookupSupportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.6
-    // Let len be the number of elements in requestedLocales.
-    size_t len = requestedLocales.size();
-    // Let subset be a new empty List.
-    ValueVector subset;
-    // Let k be 0.
-    size_t k = 0;
-    // Repeat while k < len
-    while (k < len) {
-        // Let locale be the element of requestedLocales at 0-origined list position k.
-        Value locale = requestedLocales[k];
-        // Let noExtensionsLocale be the String value that is locale with all Unicode locale extension sequences removed.
-        String* noExtensionsLocale = removeUnicodeLocaleExtension(state, locale.toString(state));
-        // Let availableLocale be the result of calling the BestAvailableLocale abstract operation (defined in 9.2.2) with arguments availableLocales and noExtensionsLocale.
-        String* availableLocale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
-        // If availableLocale is not undefined, then append locale to the end of subset.
-        if (availableLocale->length()) {
-            subset.pushBack(locale);
-        }
-        // Increment k by 1.
-        k++;
-    }
-
-    return subset;
-}
-
-static ValueVector bestfitSupportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.7
-    // TODO
-    return lookupSupportedLocales(state, availableLocales, requestedLocales);
-}
-
-Value Intl::supportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, Value options)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.8
-    Value matcher;
-    // If options is not undefined, then
-    if (!options.isUndefined()) {
-        // Let options be ToObject(options).
-        options = options.toObject(state);
-        // Let matcher be the result of calling the [[Get]] internal method of options with argument "localeMatcher".
-        matcher = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyLocaleMatcher())).value(state, options.asObject());
-        // If matcher is not undefined, then
-        if (!matcher.isUndefined()) {
-            // Let matcher be ToString(matcher).
-            matcher = matcher.toString(state);
-            // If matcher is not "lookup" or "best fit", then throw a RangeError exception.
-            if (!(matcher.asString()->equals("lookup") || matcher.asString()->equals("best fit"))) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid value on options.localeMatcher");
-            }
-        }
-    }
-
-    // If matcher is undefined or "best fit", then
-    ValueVector subset;
-    if (matcher.isUndefined() || matcher.equalsTo(state, state.context()->staticStrings().lazyBestFit().string())) {
-        // Let subset be the result of calling the BestFitSupportedLocales abstract operation (defined in 9.2.7) with arguments availableLocales and requestedLocales.
-        subset = bestfitSupportedLocales(state, availableLocales, requestedLocales);
-    } else {
-        // Let subset be the result of calling the LookupSupportedLocales abstract operation (defined in 9.2.6) with arguments availableLocales and requestedLocales.
-        subset = lookupSupportedLocales(state, availableLocales, requestedLocales);
-    }
-
-    // Return CreateArrayFromList(supportedLocales).
-    return Object::createArrayFromList(state, subset);
-}
-
-Value Intl::getOption(ExecutionState& state, Object* options, Value property, Intl::OptionValueType type, Value* values, size_t valuesLength, const Value& fallback)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.9
-    // Let value be the result of calling the [[Get]] internal method of options with argument property.
-    Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
-    // If value is not undefined, then
-    if (!value.isUndefined()) {
-        // Assert: type is "boolean" or "string".
-        // If type is "boolean", then let value be ToBoolean(value).
-        if (type == Intl::OptionValueType::BooleanValue) {
-            value = Value(value.toBoolean(state));
-        }
-        // If type is "string", then let value be ToString(value).
-        if (type == Intl::OptionValueType::StringValue) {
-            value = Value(value.toString(state));
-        }
-        // If values is not undefined, then
-        if (valuesLength) {
-            // If values does not contain an element equal to value, then throw a RangeError exception.
-            bool contains = false;
-            for (size_t i = 0; i < valuesLength; i++) {
-                if (values[i].equalsTo(state, value)) {
-                    contains = true;
-                }
-            }
-            if (!contains) {
-                ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid value");
-            }
-        }
-        // Return value.
-        return value;
-    } else {
-        // Else return fallback.
-        return fallback;
-    }
-}
-
-static std::vector<std::string> initAvailableNumberingSystems()
-{
-    std::vector<std::string> availableNumberingSystems;
-    UErrorCode status = U_ZERO_ERROR;
-    UEnumeration* numberingSystemNames = unumsys_openAvailableNames(&status);
-    ASSERT(U_SUCCESS(status));
-
-    int32_t resultLength;
-    // Numbering system names are always ASCII, so use char[].
-    while (const char* result = uenum_next(numberingSystemNames, &resultLength, &status)) {
-        ASSERT(U_SUCCESS(status));
-        auto numsys = unumsys_openByName(result, &status);
-        ASSERT(U_SUCCESS(status));
-        if (!unumsys_isAlgorithmic(numsys)) {
-            availableNumberingSystems.push_back(std::string(result, resultLength));
-        }
-        unumsys_close(numsys);
-    }
-    uenum_close(numberingSystemNames);
-
-    return availableNumberingSystems;
-}
-
-std::vector<std::string> Intl::numberingSystemsForLocale(String* locale)
-{
-    static std::vector<std::string> availableNumberingSystems = initAvailableNumberingSystems();
-
-    UErrorCode status = U_ZERO_ERROR;
-    UNumberingSystem* defaultSystem = unumsys_open(locale->toUTF8StringData().data(), &status);
-    ASSERT(U_SUCCESS(status));
-    std::string defaultSystemName(unumsys_getName(defaultSystem));
-    unumsys_close(defaultSystem);
-
-    std::vector<std::string> numberingSystems;
-    numberingSystems.push_back(defaultSystemName);
-    numberingSystems.insert(numberingSystems.end(), availableNumberingSystems.begin(), availableNumberingSystems.end());
-    return numberingSystems;
-}
-
-String* Intl::getLocaleForStringLocaleConvertCase(ExecutionState& state, Value locales)
-{
-    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-    // If requestedLocales is not an empty List, then
-    // a. Let requestedLocale be requestedLocales[0].
-    // Else Let requestedLocale be DefaultLocale().
-    String* requestedLocale = requestedLocales.size() > 0 ? requestedLocales[0].toString(state) : defaultLocale(state);
-    // Let noExtensionsLocale be the String value that is requestedLocale with all Unicode locale extension sequences (6.2.1) removed.
-    String* noExtensionsLocale = removeUnicodeLocaleExtension(state, requestedLocale);
-
-    // Let availableLocales be a List with language tags that includes the languages for which the Unicode Character Database contains language sensitive case mappings. Implementations may add additional language tags if they support case mapping for additional locales.
-    const auto& availableLocales = state.context()->vmInstance()->caseMappingAvailableLocales();
-    // Let locale be BestAvailableLocale(availableLocales, noExtensionsLocale).
-    String* locale = bestAvailableLocale(state, availableLocales, noExtensionsLocale);
-    return locale;
-}
-
-static bool is38Alphanum(const std::string& str)
-{
-    if (str.length() >= 3 && str.length() <= 8) {
-        return isAllSpecialCharacters(str, isASCIIAlphanumeric);
-    }
-    return false;
-}
-
-static bool is38AlphanumList(const std::string& str)
-{
-    std::size_t found = str.find("-");
-    if (found == std::string::npos) {
-        return is38Alphanum(str);
-    }
-    return is38Alphanum(str.substr(0, found)) && is38AlphanumList(str.substr(found + 1));
-}
-
-bool Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(String* value)
-{
-    return is38AlphanumList(value->toNonGCUTF8StringData());
-}
-
-void Intl::convertICUNumberFieldToEcmaNumberField(std::vector<NumberFieldItem>& fields, double x, const UTF16StringDataNonGCStd& resultString)
-{
-    // we need to divide integer field
-    // because icu returns result as
-    // 1.234 $
-    // "1.234" <- integer field
-    // but we want
-    // "1", "234"
-    std::vector<NumberFieldItem> integerFields;
-    for (size_t i = 0; i < fields.size(); i++) {
-        NumberFieldItem item = fields[i];
-
-        if (item.type == UNUM_INTEGER_FIELD) {
-            fields.erase(fields.begin() + i);
-            i--;
-
-            std::vector<std::pair<int32_t, int32_t>> apertures;
-
-            for (size_t j = 0; j < fields.size(); j++) {
-                if (fields[j].start >= item.start && fields[j].end <= item.end) {
-                    apertures.push_back(std::make_pair(fields[j].start, fields[j].end));
-                }
-            }
-            if (apertures.size()) {
-                NumberFieldItem newItem;
-                newItem.type = item.type;
-
-                int32_t lastStart = item.start;
-                for (size_t j = 0; j < apertures.size(); j++) {
-                    newItem.start = lastStart;
-                    newItem.end = apertures[j].first;
-                    integerFields.push_back(newItem);
-
-                    lastStart = apertures[j].second;
-                }
-
-                if (lastStart != item.end) {
-                    newItem.start = lastStart;
-                    newItem.end = item.end;
-                    integerFields.push_back(newItem);
-                }
-
-
-            } else {
-                integerFields.push_back(item);
-            }
-        }
-    }
-
-    fields.insert(fields.end(), integerFields.begin(), integerFields.end());
-
-    // add literal field if needs
-    if (!std::isnan(x) && !std::isinf(x)) {
-        std::vector<NumberFieldItem> literalFields;
-        for (size_t i = 0; i < resultString.length(); i++) {
-            bool found = false;
-            for (size_t j = 0; j < fields.size(); j++) {
-                if ((size_t)fields[j].start <= i && i < (size_t)fields[j].end) {
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                size_t end = i + 1;
-                while (end != resultString.length()) {
-                    bool found = false;
-                    for (size_t j = 0; j < fields.size(); j++) {
-                        if ((size_t)fields[j].start <= end && end < (size_t)fields[j].end) {
-                            found = true;
-                            break;
-                        }
-                    }
-                    if (found) {
-                        break;
-                    }
-                    end++;
-                }
-
-                NumberFieldItem newItem;
-                newItem.type = -1;
-                newItem.start = i;
-                newItem.end = end;
-                i = end - 1;
-                literalFields.push_back(newItem);
-            }
-        }
-        fields.insert(fields.end(), literalFields.begin(), literalFields.end());
-    }
-
-    std::sort(fields.begin(), fields.end(),
-              [](const NumberFieldItem& a, const NumberFieldItem& b) -> bool {
-                  return a.start < b.start;
-              });
-}
-
-String* Intl::icuNumberFieldToString(ExecutionState& state, int32_t fieldName, double d)
-{
-    if (fieldName == -1) {
-        return state.context()->staticStrings().lazyLiteral().string();
-    }
-
-    switch ((UNumberFormatFields)fieldName) {
-    case UNUM_INTEGER_FIELD:
-        if (std::isnan(d)) {
-            return state.context()->staticStrings().lazySmallLetterNaN().string();
-        }
-        if (std::isinf(d)) {
-            return state.context()->staticStrings().lazySmallLetterInfinity().string();
-        }
-        return state.context()->staticStrings().lazyInteger().string();
-    case UNUM_GROUPING_SEPARATOR_FIELD:
-        return state.context()->staticStrings().lazyGroup().string();
-    case UNUM_DECIMAL_SEPARATOR_FIELD:
-        return state.context()->staticStrings().lazyDecimal().string();
-    case UNUM_FRACTION_FIELD:
-        return state.context()->staticStrings().lazyFraction().string();
-    case UNUM_SIGN_FIELD:
-        return std::signbit(d) ? state.context()->staticStrings().lazyMinusSign().string() : state.context()->staticStrings().lazyPlusSign().string();
-    case UNUM_PERCENT_FIELD:
-        return state.context()->staticStrings().lazyPercentSign().string();
-    case UNUM_CURRENCY_FIELD:
-        return state.context()->staticStrings().lazyCurrency().string();
-    case UNUM_EXPONENT_SYMBOL_FIELD:
-        return state.context()->staticStrings().lazyExponentSeparator().string();
-    case UNUM_EXPONENT_SIGN_FIELD:
-        return state.context()->staticStrings().lazyExponentMinusSign().string();
-    case UNUM_EXPONENT_FIELD:
-        return state.context()->staticStrings().lazyExponentInteger().string();
-    case UNUM_MEASURE_UNIT_FIELD:
-        return state.context()->staticStrings().lazyUnit().string();
-    case UNUM_COMPACT_FIELD:
-        return state.context()->staticStrings().lazyCompact().string();
-    default:
-        ASSERT_NOT_REACHED();
-        return String::emptyString;
-    }
-}
-
-} // namespace Escargot
-
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/Intl.h
deleted file mode 100644 (file)
index 595bdce..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#ifndef __EscargotIntlObject__
-#define __EscargotIntlObject__
-
-namespace Escargot {
-
-class Intl {
-public:
-    typedef std::vector<std::string> (*LocaleDataImplFunction)(String* locale, size_t keyIndex);
-
-    struct IntlMatcherResult {
-        IntlMatcherResult()
-        {
-            extension = locale = String::emptyString;
-            extensionIndex = SIZE_MAX;
-        }
-
-        String* locale;
-        String* extension;
-        size_t extensionIndex;
-    };
-
-    static ValueVector canonicalizeLocaleList(ExecutionState& state, Value locales);
-    static StringMap resolveLocale(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, const StringMap& options, const char* const relevantExtensionKeys[], size_t relevantExtensionKeyCount, LocaleDataImplFunction localeData);
-    static Value supportedLocales(ExecutionState& state, const Vector<String*, GCUtil::gc_malloc_allocator<String*>>& availableLocales, const ValueVector& requestedLocales, Value options);
-    enum OptionValueType {
-        StringValue,
-        BooleanValue
-    };
-    static Value getOption(ExecutionState& state, Object* options, Value property, OptionValueType type, Value* values, size_t valuesLength, const Value& fallback);
-    static std::string preferredLanguage(const std::string& language);
-    static String* icuLocaleToBCP47Tag(String* string);
-    static std::vector<std::string> calendarsForLocale(String* locale);
-    static std::vector<std::string> numberingSystemsForLocale(String* locale);
-    struct CanonicalizedLangunageTag {
-        Optional<String*> canonicalizedTag;
-        std::string language;
-        std::vector<std::string> extLang;
-        std::string script;
-        std::string region;
-        std::vector<std::string> variant;
-        struct ExtensionSingleton {
-            char key;
-            std::string value;
-        };
-        std::vector<ExtensionSingleton> extensions;
-        std::vector<std::pair<std::string, std::string>> unicodeExtension;
-        std::string privateUse;
-    };
-    static CanonicalizedLangunageTag canonicalizeLanguageTag(const std::string& locale, const std::string& unicodeExtensionNameShouldIgnored = "");
-    static CanonicalizedLangunageTag isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(const std::string& locale);
-    static String* getLocaleForStringLocaleConvertCase(ExecutionState& state, Value locales);
-
-    // test string is `(3*8alphanum) *("-" (3*8alphanum))` sequence
-    static bool isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(String* value);
-
-    struct NumberFieldItem {
-        int32_t start;
-        int32_t end;
-        int32_t type;
-    };
-    static void convertICUNumberFieldToEcmaNumberField(std::vector<NumberFieldItem>& fields, double x, const UTF16StringDataNonGCStd& resultString);
-    static String* icuNumberFieldToString(ExecutionState& state, int32_t fieldName, double d);
-};
-} // namespace Escargot
-
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.cpp
deleted file mode 100644 (file)
index 5557200..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlCollator.h"
-#include "VMInstance.h"
-
-namespace Escargot {
-
-static const char* const intlCollatorRelevantExtensionKeys[3] = { "co", "kn", "kf" };
-static const int intlCollatorRelevantExtensionKeysLength = 3;
-static const size_t indexOfExtensionKeyCo = 0;
-static const size_t indexOfExtensionKeyKn = 1;
-static const size_t indexOfExtensionKeyKf = 2;
-
-static std::vector<std::string> sortLocaleData(String* locale, size_t keyIndex)
-{
-    // 9.1 Internal slots of Service Constructors & 10.2.3 Internal slots (ECMA-402 2.0)
-    std::vector<std::string> keyLocaleData;
-    switch (keyIndex) {
-    case indexOfExtensionKeyCo: {
-        // 10.2.3 "The first element of [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co must be null for all locale values."
-        keyLocaleData.push_back(std::string());
-
-        UErrorCode status = U_ZERO_ERROR;
-
-        auto utf8 = locale->toUTF8StringData();
-        UEnumeration* enumeration = ucol_getKeywordValuesForLocale("collation", utf8.data(), false, &status);
-        if (U_SUCCESS(status)) {
-            const char* collation;
-            while ((collation = uenum_next(enumeration, nullptr, &status)) && U_SUCCESS(status)) {
-                // 10.2.3 "The values "standard" and "search" must not be used as elements in any [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co array."
-                if (!strcmp(collation, "standard") || !strcmp(collation, "search"))
-                    continue;
-
-                // Map keyword values to BCP 47 equivalents.
-                if (!strcmp(collation, "dictionary"))
-                    collation = "dict";
-                else if (!strcmp(collation, "gb2312han"))
-                    collation = "gb2312";
-                else if (!strcmp(collation, "phonebook"))
-                    collation = "phonebk";
-                else if (!strcmp(collation, "traditional"))
-                    collation = "trad";
-
-                keyLocaleData.push_back(std::string(collation));
-            }
-            uenum_close(enumeration);
-        }
-        break;
-    }
-    case indexOfExtensionKeyKn:
-        keyLocaleData.push_back(std::string("false"));
-        keyLocaleData.push_back(std::string("true"));
-        break;
-    case indexOfExtensionKeyKf:
-        keyLocaleData.push_back(std::string("false"));
-        keyLocaleData.push_back(std::string("lower"));
-        keyLocaleData.push_back(std::string("upper"));
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return keyLocaleData;
-}
-
-static std::vector<std::string> searchLocaleData(String* locale, size_t keyIndex)
-{
-    // 9.1 Internal slots of Service Constructors & 10.2.3 Internal slots (ECMA-402 2.0)
-    std::vector<std::string> keyLocaleData;
-    switch (keyIndex) {
-    case indexOfExtensionKeyCo:
-        // 10.2.3 "The first element of [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co must be null for all locale values."
-        keyLocaleData.push_back(std::string());
-        break;
-    case indexOfExtensionKeyKn:
-        keyLocaleData.push_back(std::string("false"));
-        keyLocaleData.push_back(std::string("true"));
-        break;
-    case indexOfExtensionKeyKf:
-        keyLocaleData.push_back(std::string("false"));
-        keyLocaleData.push_back(std::string("lower"));
-        keyLocaleData.push_back(std::string("upper"));
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return keyLocaleData;
-}
-
-Object* IntlCollator::create(ExecutionState& state, Context* realm, Value locales, Value options)
-{
-    Object* collator = new Object(state, realm->globalObject()->objectPrototype());
-    initialize(state, collator, realm, locales, options);
-    return collator;
-}
-
-IntlCollator::CollatorResolvedOptions IntlCollator::resolvedOptions(ExecutionState& state, Object* internalSlot)
-{
-    CollatorResolvedOptions opt;
-    opt.locale = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale())).value(state, internalSlot).toString(state);
-    opt.sensitivity = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity())).value(state, internalSlot).toString(state);
-    opt.usage = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage())).value(state, internalSlot).toString(state);
-    opt.collation = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().collation)).value(state, internalSlot).toString(state);
-    opt.numeric = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().numeric)).value(state, internalSlot).toBoolean(state);
-    opt.ignorePunctuation = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation())).value(state, internalSlot).toBoolean(state);
-    opt.caseFirst = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().caseFirst)).value(state, internalSlot).toString(state);
-    return opt;
-}
-
-void IntlCollator::initialize(ExecutionState& state, Object* collator, Context* realm, Value locales, Value options)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-10.1.1.1
-
-    collator->setPrototype(state, realm->globalObject()->intlCollator()->getFunctionPrototype(state));
-    // If collator has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
-    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
-    if (collator->hasInternalSlot() && collator->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
-    }
-
-    // Set the [[initializedIntlObject]] internal property of collator to true.
-    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
-
-    // Let requestedLocales be the result of calling the
-    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-
-    // If options is undefined, then
-    // Let options be the result of creating a new object as
-    // if by the expression new Object() where Object is the standard built-in constructor with that name.
-    if (options.isUndefined()) {
-        options = new Object(state, Object::PrototypeIsNull);
-    } else {
-        // Let options be ToObject(options).
-        options = options.toObject(state);
-    }
-    // Let u be the result of calling the GetOption abstract operation (defined in 9.2.9) with arguments options,
-    // "usage", "string", a List containing the two String values "sort" and "search", and "sort".
-    Value usageValues[2] = { state.context()->staticStrings().sort.string(), state.context()->staticStrings().search.string() };
-    Value u = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUsage().string(), Intl::StringValue, usageValues, 2, usageValues[0]);
-
-    // Set the [[usage]] internal property of collator to u.
-    collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUsage()), u, collator->internalSlot());
-
-    // Let Collator be the standard built-in object that is the initial value of Intl.Collator.
-    FunctionObject* Collator = realm->globalObject()->intlCollator();
-    UNUSED_VARIABLE(Collator);
-
-    // If u is "sort", then let localeData be the value of the [[sortLocaleData]] internal property of Collator;
-    Intl::LocaleDataImplFunction localeData;
-    if (u.equalsTo(state, state.context()->staticStrings().sort.string())) {
-        localeData = sortLocaleData;
-    } else {
-        // else let localeData be the value of the [[searchLocaleData]] internal property of Collator.
-        localeData = searchLocaleData;
-    }
-
-    // Let opt be a new Record.
-    StringMap opt;
-
-    // Let matcher be the result of calling the GetOption abstract operation with arguments
-    // options, "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit"
-    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
-    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
-    // Set opt.[[localeMatcher]] to matcher.
-    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
-
-    // Table 1 – Collator options settable through both extension keys and options properties
-    // Key Property    Type            Values
-    // kn  numeric    "boolean"
-    // kf  caseFirst  "string"   "upper", "lower", "false"
-    std::function<void(String * keyColumn, Value propertyColumn, Intl::OptionValueType type, Value * values, size_t valuesSize)> doTable1 = [&](String* keyColumn, Value propertyColumn, Intl::OptionValueType type, Value* values, size_t valuesSize) {
-        // Let key be the name given in the Key column of the row.
-        Value key = keyColumn;
-
-        // Let value be the result of calling the GetOption abstract operation, passing as arguments options, the name given in the Property column of the row,
-        // the string given in the Type column of the row,
-        // a List containing the Strings given in the Values column of the row or undefined if no strings are given, and undefined.
-
-        Value value = Intl::getOption(state, options.asObject(), propertyColumn, type, values, valuesSize, Value());
-        // If the string given in the Type column of the row is "boolean" and value is not undefined, then
-        // Let value be ToString(value).
-        if (type == Intl::BooleanValue && !value.isUndefined()) {
-            value = value.toString(state);
-        }
-        // Set opt.[[<key>]] to value.
-        opt.insert(std::make_pair(keyColumn->toNonGCUTF8StringData(), value.toString(state)));
-    };
-
-    doTable1(state.context()->staticStrings().lazyKn().string(), state.context()->staticStrings().numeric.string(), Intl::BooleanValue, nullptr, 0);
-    Value caseFirstValue[3] = { state.context()->staticStrings().lazyUpper().string(), state.context()->staticStrings().lazyLower().string(), state.context()->staticStrings().stringFalse.string() };
-    doTable1(state.context()->staticStrings().lazyKf().string(), state.context()->staticStrings().caseFirst.string(), Intl::StringValue, caseFirstValue, 3);
-
-    // Let relevantExtensionKeys be the value of the [[relevantExtensionKeys]] internal property of Collator.
-    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the [[availableLocales]]
-    // internal property of Collator, requestedLocales, opt, relevantExtensionKeys, and localeData.
-    StringMap r = Intl::resolveLocale(state, realm->vmInstance()->intlCollatorAvailableLocales(), requestedLocales, opt, intlCollatorRelevantExtensionKeys, intlCollatorRelevantExtensionKeysLength, localeData);
-
-    // Set the [[locale]] internal property of collator to the value of r.[[locale]].
-    collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), collator->internalSlot());
-
-    // Let i be 0.
-    size_t i = 0;
-    // Let len be the result of calling the [[Get]] internal method of relevantExtensionKeys with argument "length".
-    size_t len = intlCollatorRelevantExtensionKeysLength;
-    // Repeat while i < len:
-    while (i < len) {
-        // Let key be the result of calling the [[Get]] internal method of relevantExtensionKeys with argument ToString(i).
-        const char* key = intlCollatorRelevantExtensionKeys[i];
-        // If key is "co", then
-        AtomicString property;
-        Value value;
-        if (strcmp(key, "co") == 0) {
-            // Let property be "collation".
-            property = state.context()->staticStrings().collation;
-            // Let value be the value of r.[[co]].
-            auto iter = r.find("co");
-            // If value is null, then let value be "default".
-            if (r.end() == iter || iter->second->equals("")) {
-                value = state.context()->staticStrings().stringDefault.string();
-            } else {
-                value = iter->second;
-            }
-        } else if (strcmp(key, "kn") == 0) {
-            // Table 1 – Collator options settable through both extension keys and options properties
-            // Key Property    Type            Values
-            // kn  numeric    "boolean"
-            // kf  caseFirst  "string"   "upper", "lower", "false"
-
-            // Else use the row of Table 1 that contains the value of key in the Key column:
-            // Let property be the name given in the Property column of the row.
-            property = state.context()->staticStrings().numeric;
-            // Let value be the value of r.[[<key>]].
-            value = r.at("kn");
-            // If the name given in the Type column of the row is "boolean",
-            // then let value be the result of comparing value with "true".
-            value = Value(value.equalsTo(state, state.context()->staticStrings().stringTrue.string()));
-
-        } else if (strcmp(key, "kf") == 0) {
-            // Table 1 – Collator options settable through both extension keys and options properties
-            // Key Property    Type            Values
-            // kn  numeric    "boolean"
-            // kf  caseFirst  "string"   "upper", "lower", "false"
-
-            // Else use the row of Table 1 that contains the value of key in the Key column:
-            // Let property be the name given in the Property column of the row.
-            property = state.context()->staticStrings().caseFirst;
-            // Let value be the value of r.[[<key>]].
-            value = r.at("kf");
-            // If the name given in the Type column of the row is "boolean",
-            // then let value be the result of comparing value with "true".
-        } else {
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-        // Set the [[<property>]] internal property of collator to value.
-        collator->internalSlot()->set(state, ObjectPropertyName(property), value, collator->internalSlot());
-        // Increase i by 1.
-        i++;
-    }
-    // Let s be the result of calling the GetOption abstract operation with arguments
-    // options, "sensitivity", "string", a List containing the four String values "base", "accent", "case", and "variant", and undefined.
-    Value sensitivityValue[4] = { state.context()->staticStrings().lazyBase().string(), state.context()->staticStrings().lazyAccent().string(), state.context()->staticStrings().lazyCase().string(), state.context()->staticStrings().lazyVariant().string() };
-    Value s = Intl::getOption(state, options.asObject(), Value(state.context()->staticStrings().lazySensitivity().string()), Intl::StringValue, sensitivityValue, 4, Value());
-    String* sensitivityString = s.toString(state);
-    // If s is undefined, then
-    // If u is "sort", then let s be "variant".
-    // Else
-    // Let dataLocale be the value of r.[[dataLocale]].
-    // Let dataLocaleData be the result of calling the [[Get]] internal operation of localeData with argument dataLocale.
-    // Let s be the result of calling the [[Get]] internal operation of dataLocaleData with argument "sensitivity".
-    if (sensitivityString->equals("base")) {
-        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyBase().string(), collator->internalSlot());
-    } else if (sensitivityString->equals("accent")) {
-        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyAccent().string(), collator->internalSlot());
-    } else if (sensitivityString->equals("case")) {
-        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyCase().string(), collator->internalSlot());
-    } else {
-        collator->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySensitivity()), state.context()->staticStrings().lazyVariant().string(), collator->internalSlot());
-    }
-
-    // Let ip be the result of calling the GetOption abstract operation with arguments options, "ignorePunctuation", "boolean", undefined, and false.
-    Value ip = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyIgnorePunctuation().string(), Intl::BooleanValue, nullptr, 0, Value(false));
-    // Set the [[ignorePunctuation]] internal property of collator to ip.
-    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyIgnorePunctuation()), ObjectPropertyDescriptor(ip));
-    // Set the [[boundCompare]] internal property of collator to undefined.
-    // Set the [[initializedCollator]] internal property of collator to true.
-    collator->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedCollator()), ObjectPropertyDescriptor(Value(true)));
-    // Return collator.
-
-    {
-        Object* internalSlot = collator->internalSlot();
-        CollatorResolvedOptions opt = resolvedOptions(state, internalSlot);
-        UErrorCode status = U_ZERO_ERROR;
-        String* locale = opt.locale;
-        UColAttributeValue strength = UCOL_DEFAULT;
-        UColAttributeValue caseLevel = UCOL_OFF;
-        UColAttributeValue alternate = UCOL_DEFAULT;
-        UColAttributeValue numeric = UCOL_OFF;
-        UColAttributeValue normalization = UCOL_ON; // normalization is always on. ecma-402 needs this
-        UColAttributeValue caseFirst = UCOL_DEFAULT;
-
-        if (opt.usage->equals("search")) {
-            // If usage is search, we should append "-co-search" extension
-            size_t u = locale->find("-u-");
-            if (u == SIZE_MAX) {
-                StringBuilder sb;
-                sb.appendString(locale);
-                sb.appendString("-u-co-search");
-                locale = sb.finalize();
-            } else {
-                StringBuilder sb;
-                sb.appendString(locale);
-                sb.appendString("-co-search");
-                locale = sb.finalize();
-            }
-        } else {
-            ASSERT(opt.usage->equals("sort"));
-        }
-
-
-        String* sensitivity = opt.sensitivity;
-
-        if (sensitivity->equals("base")) {
-            strength = UCOL_PRIMARY;
-        } else if (sensitivity->equals("accent")) {
-            strength = UCOL_SECONDARY;
-        } else if (sensitivity->equals("case")) {
-            strength = UCOL_PRIMARY;
-            caseLevel = UCOL_ON;
-        } else {
-            ASSERT(sensitivity->equals("variant"));
-            strength = UCOL_TERTIARY;
-        }
-
-        if (opt.ignorePunctuation) {
-            alternate = UCOL_SHIFTED;
-        }
-
-        if (opt.numeric) {
-            numeric = UCOL_ON;
-        }
-
-        String* caseFirstString = opt.caseFirst;
-        if (caseFirstString->equals("upper")) {
-            caseFirst = UCOL_UPPER_FIRST;
-        } else if (caseFirstString->equals("lower")) {
-            caseFirst = UCOL_LOWER_FIRST;
-        } else {
-            ASSERT(caseFirstString->equals("false"));
-            caseFirst = UCOL_OFF;
-        }
-
-        UCollator* ucollator = ucol_open(locale->toUTF8StringData().data(), &status);
-        if (U_FAILURE(status)) {
-            return;
-        }
-
-        ucol_setAttribute(ucollator, UCOL_STRENGTH, strength, &status);
-        ucol_setAttribute(ucollator, UCOL_CASE_LEVEL, caseLevel, &status);
-        ucol_setAttribute(ucollator, UCOL_ALTERNATE_HANDLING, alternate, &status);
-        ucol_setAttribute(ucollator, UCOL_NUMERIC_COLLATION, numeric, &status);
-        ucol_setAttribute(ucollator, UCOL_NORMALIZATION_MODE, normalization, &status);
-        ucol_setAttribute(ucollator, UCOL_CASE_FIRST, caseFirst, &status);
-
-        if (U_FAILURE(status)) {
-            ucol_close(ucollator);
-            return;
-        }
-
-        internalSlot->setExtraData(ucollator);
-
-        internalSlot->addFinalizer([](Object* obj, void* data) {
-            Object* self = (Object*)obj;
-            ucol_close((UCollator*)self->extraData());
-        },
-                                   nullptr);
-    }
-}
-
-int IntlCollator::compare(ExecutionState& state, Object* collator, String* a, String* b)
-{
-    if (a->equals(b)) {
-        return 0;
-    }
-
-    auto utf16A = a->toUTF16StringData();
-    auto utf16B = b->toUTF16StringData();
-
-    UCollator* ucol = (UCollator*)collator->internalSlot()->extraData();
-    UCollationResult result = ucol_strcoll(ucol, utf16A.data(), utf16A.length(), utf16B.data(), utf16B.length());
-
-    switch (result) {
-    case UCOL_LESS:
-        return -1;
-    case UCOL_EQUAL:
-        return 0;
-    case UCOL_GREATER:
-        return 1;
-    default:
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to compare string a and b");
-    }
-
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlCollator.h
deleted file mode 100644 (file)
index 32b474c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlCollator__
-#define __EscargotIntlCollator__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlCollator {
-public:
-    struct CollatorResolvedOptions {
-        String* locale;
-        String* sensitivity;
-        String* usage;
-        String* collation;
-        bool numeric;
-        bool ignorePunctuation;
-        String* caseFirst;
-    };
-
-    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
-    static CollatorResolvedOptions resolvedOptions(ExecutionState& state, Object* internalSlot);
-    static void initialize(ExecutionState& state, Object* collator, Context* realm, Value locales, Value options);
-    static int compare(ExecutionState& state, Object* collator, String* a, String* b);
-};
-
-} // namespace Escargot
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.cpp
deleted file mode 100644 (file)
index b3d7f50..0000000
+++ /dev/null
@@ -1,1021 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "VMInstance.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlDateTimeFormat.h"
-#include "DateObject.h"
-#include "ArrayObject.h"
-
-namespace Escargot {
-
-static const char* const intlDateTimeFormatRelevantExtensionKeys[3] = { "ca", "nu", "hc" };
-static size_t intlDateTimeFormatRelevantExtensionKeysLength = 3;
-static const size_t indexOfExtensionKeyCa = 0;
-static const size_t indexOfExtensionKeyNu = 1;
-static const size_t indexOfExtensionKeyHc = 2;
-static const double minECMAScriptTime = -8.64E15;
-
-std::vector<std::string> Intl::calendarsForLocale(String* locale)
-{
-    std::vector<std::string> keyLocaleData;
-    UErrorCode status = U_ZERO_ERROR;
-    UEnumeration* calendars = ucal_getKeywordValuesForLocale("calendar", locale->toUTF8StringData().data(), false, &status);
-    ASSERT(U_SUCCESS(status));
-
-    status = U_ZERO_ERROR;
-    int32_t nameLength;
-    while (const char* availableName = uenum_next(calendars, &nameLength, &status)) {
-        ASSERT(U_SUCCESS(status));
-        status = U_ZERO_ERROR;
-        std::string calendar = std::string(availableName, nameLength);
-        // Ensure aliases used in language tag are allowed.
-        if (calendar == std::string("gregorian")) {
-            keyLocaleData.push_back(std::string("gregory"));
-        } else if (calendar == std::string("islamic-civil")) {
-            keyLocaleData.push_back(std::string("islamicc"));
-        } else if (calendar == std::string("ethiopic-amete-alem")) {
-            keyLocaleData.push_back(std::string("ethioaa"));
-        } else {
-            keyLocaleData.push_back(calendar);
-        }
-    }
-    uenum_close(calendars);
-
-    return keyLocaleData;
-}
-
-static std::vector<std::string> localeDataDateTimeFormat(String* locale, size_t keyIndex)
-{
-    std::vector<std::string> keyLocaleData;
-    switch (keyIndex) {
-    case indexOfExtensionKeyCa:
-        keyLocaleData = Intl::calendarsForLocale(locale);
-        break;
-    case indexOfExtensionKeyNu:
-        keyLocaleData = Intl::numberingSystemsForLocale(locale);
-        break;
-    case indexOfExtensionKeyHc:
-        keyLocaleData.push_back("h12");
-        keyLocaleData.push_back("h23");
-        keyLocaleData.push_back("h24");
-        keyLocaleData.push_back("h11");
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return keyLocaleData;
-}
-
-static bool equalIgnoringASCIICase(String* timeZoneName, const UTF16StringDataNonGCStd& ianaTimeZoneView)
-{
-    if (timeZoneName->length() != ianaTimeZoneView.size()) {
-        return false;
-    }
-    for (size_t i = 0; i < ianaTimeZoneView.size(); i++) {
-        if (tolower(ianaTimeZoneView[i]) != tolower(timeZoneName->charAt(i))) {
-            return false;
-        }
-    }
-    return true;
-}
-
-static String* canonicalizeTimeZoneName(ExecutionState& state, String* timeZoneName)
-{
-    // 6.4.1 IsValidTimeZoneName (timeZone)
-    // The abstract operation returns true if timeZone, converted to upper case as described in 6.1, is equal to one of the Zone or Link names of the IANA Time Zone Database, converted to upper case as described in 6.1. It returns false otherwise.
-    UErrorCode status = U_ZERO_ERROR;
-    UEnumeration* timeZones = ucal_openTimeZones(&status);
-    ASSERT(U_SUCCESS(status));
-
-    String* canonical = String::emptyString;
-    do {
-        status = U_ZERO_ERROR;
-        int32_t ianaTimeZoneLength;
-        // Time zone names are respresented as UChar[] in all related ICU apis.
-        const UChar* ianaTimeZone = uenum_unext(timeZones, &ianaTimeZoneLength, &status);
-        ASSERT(U_SUCCESS(status));
-
-        // End of enumeration.
-        if (!ianaTimeZone)
-            break;
-
-        UTF16StringDataNonGCStd ianaTimeZoneView((char16_t*)ianaTimeZone, ianaTimeZoneLength);
-        if (!equalIgnoringASCIICase(timeZoneName, ianaTimeZoneView))
-            continue;
-
-        // Found a match, now canonicalize.
-        // 6.4.2 CanonicalizeTimeZoneName (timeZone) (ECMA-402 2.0)
-        // 1. Let ianaTimeZone be the Zone or Link name of the IANA Time Zone Database such that timeZone, converted to upper case as described in 6.1, is equal to ianaTimeZone, converted to upper case as described in 6.1.
-        // 2. If ianaTimeZone is a Link name, then let ianaTimeZone be the corresponding Zone name as specified in the “backward” file of the IANA Time Zone Database.
-
-        UTF16StringDataNonGCStd buffer;
-        buffer.resize(ianaTimeZoneLength);
-        UBool isSystemID = false;
-        status = U_ZERO_ERROR;
-        auto canonicalLength = ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, (UChar*)buffer.data(), ianaTimeZoneLength, &isSystemID, &status);
-        if (status == U_BUFFER_OVERFLOW_ERROR) {
-            buffer.resize(canonicalLength);
-            isSystemID = false;
-            status = U_ZERO_ERROR;
-            ucal_getCanonicalTimeZoneID(ianaTimeZone, ianaTimeZoneLength, (UChar*)buffer.data(), canonicalLength, &isSystemID, &status);
-        }
-        ASSERT(U_SUCCESS(status));
-        canonical = new UTF16String(buffer.data(), canonicalLength);
-    } while (canonical->length() == 0);
-    uenum_close(timeZones);
-
-    // 3. If ianaTimeZone is "Etc/UTC" or "Etc/GMT", then return "UTC".
-    if (canonical->equals("Etc/UTC") || canonical->equals("Etc/GMT")) {
-        canonical = state.context()->staticStrings().UTC.string();
-    }
-
-    // 4. Return ianaTimeZone.
-    return canonical;
-}
-
-
-static void toDateTimeOptionsTest(ExecutionState& state, Value options, AtomicString name, bool& needDefaults)
-{
-    Value r = options.asObject()->get(state, name).value(state, options.asObject());
-    if (!r.isUndefined()) {
-        needDefaults = false;
-    }
-}
-
-static String* defaultTimeZone(ExecutionState& state)
-{
-    // ensure timezone
-    state.context()->vmInstance()->timezone();
-    return String::fromUTF8(state.context()->vmInstance()->timezoneID().data(), state.context()->vmInstance()->timezoneID().length());
-}
-
-Object* IntlDateTimeFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
-{
-    Object* dateTimeFormat = new Object(state, realm->globalObject()->intlDateTimeFormatPrototype());
-    initialize(state, dateTimeFormat, locales, options);
-    return dateTimeFormat;
-}
-
-static std::string readHourCycleFromPattern(const UTF16StringDataNonGCStd& patternString)
-{
-    bool inQuote = false;
-    for (size_t i = 0; i < patternString.length(); i++) {
-        auto ch = patternString[i];
-        switch (ch) {
-        case '\'':
-            inQuote = !inQuote;
-            break;
-        case 'K':
-            if (!inQuote) {
-                return "h11";
-            }
-            break;
-        case 'h':
-            if (!inQuote) {
-                return "h12";
-            }
-            break;
-        case 'H':
-            if (!inQuote) {
-                return "h23";
-            }
-            break;
-        case 'k':
-            if (!inQuote) {
-                return "h24";
-            }
-            break;
-        }
-    }
-    return "";
-}
-
-UTF16StringDataNonGCStd updateHourCycleInPatternDueToHourCycle(const UTF16StringDataNonGCStd& pattern, String* hc)
-{
-    char16_t newHcChar;
-    if (hc->equals("h11")) {
-        newHcChar = 'K';
-    } else if (hc->equals("h12")) {
-        newHcChar = 'h';
-    } else if (hc->equals("h23")) {
-        newHcChar = 'H';
-    } else {
-        ASSERT(hc->equals("h24"));
-        newHcChar = 'k';
-    }
-    bool inQuote = false;
-    UTF16StringDataNonGCStd result;
-    for (size_t i = 0; i < pattern.length(); i++) {
-        auto ch = pattern[i];
-        switch (ch) {
-        case '\'':
-            inQuote = !inQuote;
-            result += ch;
-            break;
-        case 'K':
-        case 'k':
-        case 'H':
-        case 'h':
-            result += inQuote ? ch : newHcChar;
-            break;
-        default:
-            result += ch;
-            break;
-        }
-    }
-
-    return result;
-}
-
-
-void IntlDateTimeFormat::initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options)
-{
-    // If dateTimeFormat has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
-    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
-    if (dateTimeFormat->hasInternalSlot() && dateTimeFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
-    }
-
-    // Set the [[initializedIntlObject]] internal property of dateTimeFormat to true.
-    dateTimeFormat->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
-
-    // Let requestedLocales be the result of calling the
-    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-
-    // Let options be the result of calling the ToDateTimeOptions abstract operation (defined below) with arguments options, "any", and "date".
-    options = toDateTimeOptions(state, options, state.context()->staticStrings().lazyAny().string(), state.context()->staticStrings().lazyDate().string());
-
-    // Let opt be a new Record.
-    StringMap opt;
-    // Let matcher be the result of calling the GetOption abstract operation (defined in 9.2.9) with arguments options,
-    // "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit".
-    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
-    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
-
-    // Set opt.[[localeMatcher]] to matcher.
-    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
-
-    // Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined).
-    Value calendar = Intl::getOption(state, options.asObject(), state.context()->staticStrings().calendar.string(), Intl::StringValue, nullptr, 0, Value());
-    // If calendar is not undefined, then
-    if (!calendar.isUndefined()) {
-        // If calendar does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
-        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(calendar.asString())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The calendar value you gave is not valid");
-        }
-    }
-    // Set opt.[[ca]] to calendar.
-    if (!calendar.isUndefined()) {
-        opt.insert(std::make_pair("ca", calendar.toString(state)));
-    }
-    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
-    Value numberingSystem = Intl::getOption(state, options.asObject(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
-    // If numberingSystem is not undefined, then
-    if (!numberingSystem.isUndefined()) {
-        // If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
-        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
-        }
-    }
-    // Set opt.[[nu]] to numberingSystem.
-    if (!numberingSystem.isUndefined()) {
-        opt.insert(std::make_pair("nu", numberingSystem.toString(state)));
-    }
-
-    // Let hour12 be ? GetOption(options, "hour12", "boolean", undefined, undefined).
-    Value hour12 = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyHour12().string(), Intl::BooleanValue, nullptr, 0, Value());
-
-    // Let hourCycle be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
-    Value hourCycleValue[4] = { state.context()->staticStrings().lazyH11().string(), state.context()->staticStrings().lazyH12().string(), state.context()->staticStrings().lazyH23().string(), state.context()->staticStrings().lazyH24().string() };
-    Value hourCycle = Intl::getOption(state, options.asObject(), state.context()->staticStrings().hourCycle.string(), Intl::StringValue, hourCycleValue, 4, Value());
-    // If hour12 is not undefined, then
-    if (!hour12.isUndefined()) {
-        // Let hourCycle be null.
-        hourCycle = Value(Value::Null);
-    }
-    // Set opt.[[hc]] to hourCycle.
-    if (!hourCycle.isUndefinedOrNull()) {
-        opt.insert(std::make_pair("hc", hourCycle.toString(state)));
-    }
-
-    // Let DateTimeFormat be the standard built-in object that is the initial value of Intl.DateTimeFormat.
-    // Let localeData be the value of the [[localeData]] internal property of DateTimeFormat.
-    const auto& availableLocales = state.context()->vmInstance()->intlDateTimeFormatAvailableLocales();
-
-    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the
-    // [[availableLocales]] internal property of DateTimeFormat, requestedLocales, opt, the [[relevantExtensionKeys]] internal property of DateTimeFormat, and localeData.
-    StringMap r = Intl::resolveLocale(state, availableLocales, requestedLocales, opt, intlDateTimeFormatRelevantExtensionKeys, intlDateTimeFormatRelevantExtensionKeysLength, localeDataDateTimeFormat);
-
-    // The resolved locale doesn't include a hc Unicode extension value if the hour12 or hourCycle option is also present.
-    if (!hour12.isUndefined() || !hourCycle.isUndefinedOrNull()) {
-        auto iter = r.find("locale");
-        String* locale = iter->second;
-        iter->second = Intl::canonicalizeLanguageTag(locale->toNonGCUTF8StringData(), "hc").canonicalizedTag.value();
-    }
-
-    // Set the [[locale]] internal property of dateTimeFormat to the value of r.[[locale]].
-    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), dateTimeFormat->internalSlot());
-    // Set the [[calendar]] internal property of dateTimeFormat to the value of r.[[ca]].
-    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().calendar), r.at("ca"), dateTimeFormat->internalSlot());
-    // Set dateTimeFormat.[[hourCycle]] to r.[[hc]].
-    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), r.at("hc"), dateTimeFormat->internalSlot());
-    // Set the [[numberingSystem]] internal property of dateTimeFormat to the value of r.[[nu]].
-    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), r.at("nu"), dateTimeFormat->internalSlot());
-
-    // Let dataLocale be the value of r.[[dataLocale]].
-    Value dataLocale = r.at("dataLocale");
-
-    // Always use ICU date format generator, rather than our own pattern list and matcher.
-    UErrorCode status = U_ZERO_ERROR;
-    LocalResourcePointer<UDateTimePatternGenerator> generator(udatpg_open(dataLocale.toString(state)->toUTF8StringData().data(), &status),
-                                                              [](UDateTimePatternGenerator* d) { udatpg_close(d); });
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
-        return;
-    }
-
-    // Let tz be the result of calling the [[Get]] internal method of options with argument "timeZone".
-    Value tz = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, options.asObject());
-
-    // If tz is not undefined, then
-    if (!tz.isUndefined()) {
-        // Let tz be ToString(tz).
-        String* tzString = tz.toString(state);
-        // Convert tz to upper case as described in 6.1.
-        // NOTE:   If an implementation accepts additional time zone values, as permitted under certain conditions by the Conformance clause,
-        // different casing rules apply., If tz is not "UTC", then throw a RangeError exception.
-        tz = canonicalizeTimeZoneName(state, tzString);
-        tzString = tz.toString(state);
-        if (tzString->length() == 0) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid timezone value");
-        }
-    } else {
-        tz = defaultTimeZone(state);
-    }
-    // Set the [[timeZone]] internal property of dateTimeFormat to tz.
-    dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone()), tz, dateTimeFormat->internalSlot());
-
-    // Let opt be a new Record.
-    opt.clear();
-
-    // Table 3 – Components of date and time formats
-    // Property    Values
-    // weekday "narrow", "short", "long"
-    // era "narrow", "short", "long"
-    // year    "2-digit", "numeric"
-    // month   "2-digit", "numeric", "narrow", "short", "long"
-    // day "2-digit", "numeric"
-    // hour    "2-digit", "numeric"
-    // minute  "2-digit", "numeric"
-    // second  "2-digit", "numeric"
-    // timeZoneName    "short", "long"
-
-    // For each row of Table 3, except the header row, do:
-    std::function<void(String * prop, Value * values, size_t valuesSize)> doTable3 = [&](String* prop, Value* values, size_t valuesSize) {
-        // Let prop be the name given in the Property column of the row.
-        // Let value be the result of calling the GetOption abstract operation, passing as argument options, the name given in the Property column of the row,
-        // "string", a List containing the strings given in the Values column of the row, and undefined.
-        Value value = Intl::getOption(state, options.asObject(), prop, Intl::StringValue, values, valuesSize, Value());
-        // Set opt.[[<prop>]] to value.
-        if (!value.isUndefined()) {
-            opt.insert(std::make_pair(prop->toNonGCUTF8StringData(), value.toString(state)));
-        }
-    };
-
-    StringBuilder skeletonBuilder;
-
-    Value narrowShortLongValues[3] = { state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
-
-    doTable3(state.context()->staticStrings().lazyWeekday().string(), narrowShortLongValues, 3);
-
-    String* ret = opt.at("weekday");
-
-    if (ret->equals("narrow")) {
-        skeletonBuilder.appendString("EEEEE");
-    } else if (ret->equals("short")) {
-        skeletonBuilder.appendString("EEE");
-    } else if (ret->equals("long")) {
-        skeletonBuilder.appendString("EEEE");
-    }
-
-    doTable3(state.context()->staticStrings().lazyEra().string(), narrowShortLongValues, 3);
-
-    ret = opt.at("era");
-    if (ret->equals("narrow")) {
-        skeletonBuilder.appendString("GGGGG");
-    } else if (ret->equals("short")) {
-        skeletonBuilder.appendString("GGG");
-    } else if (ret->equals("long")) {
-        skeletonBuilder.appendString("GGGG");
-    }
-
-    Value twoDightNumericValues[2] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string() };
-    doTable3(state.context()->staticStrings().lazyYear().string(), twoDightNumericValues, 2);
-
-    ret = opt.at("year");
-    if (ret->equals("2-digit")) {
-        skeletonBuilder.appendString("yy");
-    } else if (ret->equals("numeric")) {
-        skeletonBuilder.appendString("y");
-    }
-
-    Value allValues[5] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string(), state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
-    doTable3(state.context()->staticStrings().lazyMonth().string(), allValues, 5);
-
-    ret = opt.at("month");
-    if (ret->equals("2-digit")) {
-        skeletonBuilder.appendString("MM");
-    } else if (ret->equals("numeric")) {
-        skeletonBuilder.appendString("M");
-    } else if (ret->equals("narrow")) {
-        skeletonBuilder.appendString("MMMMM");
-    } else if (ret->equals("short")) {
-        skeletonBuilder.appendString("MMM");
-    } else if (ret->equals("long")) {
-        skeletonBuilder.appendString("MMMM");
-    }
-
-    doTable3(state.context()->staticStrings().lazyDay().string(), twoDightNumericValues, 2);
-
-    ret = opt.at("day");
-    if (ret->equals("2-digit")) {
-        skeletonBuilder.appendString("dd");
-    } else if (ret->equals("numeric")) {
-        skeletonBuilder.appendString("d");
-    }
-
-    doTable3(state.context()->staticStrings().lazyHour().string(), twoDightNumericValues, 2);
-
-    String* hour = ret = opt.at("hour");
-    Value hr12Value = hour12;
-    bool isHour12Undefined = hr12Value.isUndefined();
-    bool hr12 = hr12Value.toBoolean(state);
-
-    if (isHour12Undefined) {
-        if (ret->equals("2-digit"))
-            skeletonBuilder.appendString("jj");
-        else if (ret->equals("numeric"))
-            skeletonBuilder.appendChar('j');
-    } else if (hr12) {
-        if (ret->equals("2-digit"))
-            skeletonBuilder.appendString("hh");
-        else if (ret->equals("numeric"))
-            skeletonBuilder.appendChar('h');
-    } else {
-        if (ret->equals("2-digit"))
-            skeletonBuilder.appendString("HH");
-        else if (ret->equals("numeric"))
-            skeletonBuilder.appendChar('H');
-    }
-
-    doTable3(state.context()->staticStrings().lazyMinute().string(), twoDightNumericValues, 2);
-
-    ret = opt.at("minute");
-    if (ret->equals("2-digit")) {
-        skeletonBuilder.appendString("mm");
-    } else if (ret->equals("numeric")) {
-        skeletonBuilder.appendString("m");
-    }
-
-    doTable3(state.context()->staticStrings().lazySecond().string(), twoDightNumericValues, 2);
-
-    ret = opt.at("second");
-    if (ret->equals("2-digit")) {
-        skeletonBuilder.appendString("ss");
-    } else if (ret->equals("numeric")) {
-        skeletonBuilder.appendString("s");
-    }
-
-    Value shortLongValues[2] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
-    doTable3(state.context()->staticStrings().lazyTimeZoneName().string(), shortLongValues, 2);
-
-    ret = opt.at("timeZoneName");
-    if (ret->equals("short")) {
-        skeletonBuilder.appendString("z");
-    } else if (ret->equals("long")) {
-        skeletonBuilder.appendString("zzzz");
-    }
-
-    // Let dataLocaleData be the result of calling the [[Get]] internal method of localeData with argument dataLocale.
-    // Let formats be the result of calling the [[Get]] internal method of dataLocaleData with argument "formats".
-    // Let matcher be the result of calling the GetOption abstract operation with arguments options,
-    // "formatMatcher", "string", a List containing the two String values "basic" and "best fit", and "best fit".
-    Value formatMatcherValues[2] = { state.context()->staticStrings().lazyBasic().string(), state.context()->staticStrings().lazyBestFit().string() };
-    matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyFormatMatcher().string(), Intl::StringValue, formatMatcherValues, 2, formatMatcherValues[1]);
-
-    // Always use ICU date format generator, rather than our own pattern list and matcher.
-    // Covers steps 28-36.
-    String* skeleton = skeletonBuilder.finalize();
-    UTF16StringData skeletonUTF16String = skeleton->toUTF16StringData();
-
-    // If dateTimeFormat.[[Hour]] is not undefined, then
-    bool hasHourOption = hour->length();
-    if (hasHourOption) {
-        // Let hcDefault be dataLocaleData.[[hourCycle]].
-        UTF16StringDataNonGCStd patternBuffer;
-        patternBuffer.resize(32);
-        status = U_ZERO_ERROR;
-        auto patternLength = udatpg_getBestPattern(generator.get(), u"jjmm", 4, (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
-        patternBuffer.resize(patternLength);
-        if (status == U_BUFFER_OVERFLOW_ERROR) {
-            status = U_ZERO_ERROR;
-            patternBuffer.resize(patternLength);
-            udatpg_getBestPattern(generator.get(), u"jjmm", 4, (UChar*)patternBuffer.data(), patternLength, &status);
-        }
-        ASSERT(U_SUCCESS(status));
-        auto hcDefault = readHourCycleFromPattern(patternBuffer);
-        // Let hc be dateTimeFormat.[[HourCycle]].
-        auto hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot()).asString();
-        // If hc is null, then
-        if (!hc->length()) {
-            // Set hc to hcDefault.
-            hc = String::fromUTF8(hcDefault.data(), hcDefault.size());
-        }
-        // If hour12 is not undefined, then
-        if (!hour12.isUndefined()) {
-            // If hour12 is true, then
-            if (hour12.asBoolean()) {
-                // If hcDefault is "h11" or "h23", then
-                if (hcDefault == "h11" || hcDefault == "h23") {
-                    // Set hc to "h11".
-                    hc = state.context()->staticStrings().lazyH11().string();
-                } else {
-                    // Set hc to "h12".
-                    hc = state.context()->staticStrings().lazyH12().string();
-                }
-            } else {
-                // Assert: hour12 is false.
-                // If hcDefault is "h11" or "h23", then
-                if (hcDefault == "h11" || hcDefault == "h23") {
-                    // Set hc to "h23".
-                    hc = state.context()->staticStrings().lazyH23().string();
-                } else {
-                    // Else,
-                    // Set hc to "h24".
-                    hc = state.context()->staticStrings().lazyH24().string();
-                }
-            }
-        }
-
-        // Let dateTimeFormat.[[HourCycle]] to hc.
-        dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(hc), dateTimeFormat->internalSlot());
-    } else {
-        // Set dateTimeFormat.[[HourCycle]] to undefined.
-        dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(), dateTimeFormat->internalSlot());
-        // Let pattern be bestFormat.[[pattern]].
-    }
-
-    UTF16StringDataNonGCStd patternBuffer;
-    patternBuffer.resize(32);
-    status = U_ZERO_ERROR;
-    auto patternLength = udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
-    patternBuffer.resize(patternLength);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        patternBuffer.resize(patternLength);
-        udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternLength, &status);
-    }
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
-        return;
-    }
-
-    Value hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot());
-    if (!hc.isUndefined() && hc.asString()->length()) {
-        patternBuffer = updateHourCycleInPatternDueToHourCycle(patternBuffer, hc.asString());
-    }
-
-    bool inQuote = false;
-    unsigned length = patternBuffer.length();
-    for (unsigned i = 0; i < length; ++i) {
-        char16_t currentCharacter = patternBuffer[i];
-
-        if (currentCharacter == '\'') {
-            inQuote = !inQuote;
-        }
-
-        if (!isASCIIAlpha(currentCharacter))
-            continue;
-
-        unsigned count = 1;
-        while (i + 1 < length && patternBuffer[i + 1] == currentCharacter) {
-            ++count;
-            ++i;
-        }
-
-        if (hasHourOption && !inQuote) {
-            if (currentCharacter == 'h' || currentCharacter == 'K') {
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(true), dateTimeFormat->internalSlot());
-            } else if (currentCharacter == 'H' || currentCharacter == 'k') {
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(false), dateTimeFormat->internalSlot());
-            }
-        }
-
-        switch (currentCharacter) {
-        case 'G':
-            if (count <= 3)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
-            else if (count == 4)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
-            else if (count == 5)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'y':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'M':
-        case 'L':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            else if (count == 3)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
-            else if (count == 4)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
-            else if (count == 5)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'E':
-        case 'e':
-        case 'c':
-            if (count <= 3)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
-            else if (count == 4)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
-            else if (count == 5)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'd':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'h':
-        case 'H':
-        case 'k':
-        case 'K':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'm':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            break;
-        case 's':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
-            else if (count == 2)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
-            break;
-        case 'z':
-        case 'v':
-        case 'V':
-            if (count == 1)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
-            else if (count == 4)
-                dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
-            break;
-        }
-    }
-
-    status = U_ZERO_ERROR;
-    UTF16StringData timeZoneView = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, dateTimeFormat->internalSlot()).toString(state)->toUTF16StringData();
-    UTF8StringData localeStringView = r.at("locale")->toUTF8StringData();
-    UDateFormat* icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, localeStringView.data(), (UChar*)timeZoneView.data(), timeZoneView.length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
-        return;
-    }
-
-    dateTimeFormat->internalSlot()->setExtraData(icuDateFormat);
-
-    dateTimeFormat->internalSlot()->addFinalizer([](Object* obj, void* data) {
-        Object* self = (Object*)obj;
-        udat_close((UDateFormat*)self->extraData());
-    },
-                                                 nullptr);
-
-    // Set dateTimeFormat.[[boundFormat]] to undefined.
-    // Set dateTimeFormat.[[initializedDateTimeFormat]] to true.
-    dateTimeFormat->internalSlot()->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()), ObjectPropertyDescriptor(Value(true)));
-
-    status = U_ZERO_ERROR;
-    UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(icuDateFormat));
-    std::string type(ucal_getType(cal, &status));
-    if (status == U_ZERO_ERROR && std::string("gregorian") == type) {
-        ucal_setGregorianChange(cal, minECMAScriptTime, &status);
-    }
-    // Return dateTimeFormat.
-    return;
-}
-
-UTF16StringDataNonGCStd IntlDateTimeFormat::format(ExecutionState& state, Object* dateTimeFormat, double x)
-{
-    // If x is not a finite Number, then throw a RangeError exception.
-    // If x is NaN, throw a RangeError exception
-    // If abs(time) > 8.64 × 10^15, return NaN.
-    if (std::isinf(x) || std::isnan(x) || !IS_IN_TIME_RANGE(x)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "date value is valid in DateTimeFormat format()");
-    }
-
-    x = Value(x).toInteger(state);
-
-    UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
-
-    // Delegate remaining steps to ICU.
-    UErrorCode status = U_ZERO_ERROR;
-    UTF16StringDataNonGCStd result;
-    result.resize(32);
-    auto resultLength = udat_format(udat, x, (UChar*)result.data(), result.size(), nullptr, &status);
-    result.resize(resultLength);
-
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        udat_format(udat, x, (UChar*)result.data(), resultLength, nullptr, &status);
-    }
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format date value");
-    }
-
-    return result;
-}
-
-
-static String* icuFieldTypeToPartName(ExecutionState& state, int32_t fieldName)
-{
-    if (fieldName == -1) {
-        return state.context()->staticStrings().lazyLiteral().string();
-    }
-
-    switch ((UDateFormatField)fieldName) {
-    case UDAT_ERA_FIELD:
-        return state.context()->staticStrings().lazyEra().string();
-    case UDAT_YEAR_FIELD:
-    case UDAT_YEAR_WOY_FIELD:
-    case UDAT_EXTENDED_YEAR_FIELD:
-    case UDAT_YEAR_NAME_FIELD:
-        return state.context()->staticStrings().lazyYear().string();
-    case UDAT_MONTH_FIELD:
-    case UDAT_STANDALONE_MONTH_FIELD:
-        return state.context()->staticStrings().lazyMonth().string();
-    case UDAT_DATE_FIELD:
-    case UDAT_JULIAN_DAY_FIELD:
-        return state.context()->staticStrings().lazyDay().string();
-    case UDAT_HOUR_OF_DAY1_FIELD:
-    case UDAT_HOUR_OF_DAY0_FIELD:
-    case UDAT_HOUR1_FIELD:
-    case UDAT_HOUR0_FIELD:
-        return state.context()->staticStrings().lazyHour().string();
-    case UDAT_MINUTE_FIELD:
-        return state.context()->staticStrings().lazyMinute().string();
-    case UDAT_SECOND_FIELD:
-        return state.context()->staticStrings().lazySecond().string();
-    case UDAT_DAY_OF_WEEK_FIELD:
-    case UDAT_STANDALONE_DAY_FIELD:
-    case UDAT_DOW_LOCAL_FIELD:
-    case UDAT_DAY_OF_WEEK_IN_MONTH_FIELD:
-        return state.context()->staticStrings().lazyWeekday().string();
-    case UDAT_AM_PM_FIELD:
-        return state.context()->staticStrings().lazyDayPeriod().string();
-    case UDAT_TIMEZONE_FIELD:
-        return state.context()->staticStrings().lazyTimeZoneName().string();
-    default:
-        ASSERT_NOT_REACHED();
-        return String::emptyString;
-    }
-}
-
-
-ArrayObject* IntlDateTimeFormat::formatToParts(ExecutionState& state, Object* dateTimeFormat, double x)
-{
-    // If x is not a finite Number, then throw a RangeError exception.
-    // If x is NaN, throw a RangeError exception
-    // If abs(time) > 8.64 × 10^15, return NaN.
-    if (std::isinf(x) || std::isnan(x) || !IS_IN_TIME_RANGE(x)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "date value is not valid in DateTimeFormat formatToParts()");
-    }
-
-    x = Value(x).toInteger(state);
-
-    ArrayObject* result = new ArrayObject(state);
-
-    UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
-
-    UErrorCode status = U_ZERO_ERROR;
-
-    UFieldPositionIterator* fpositer;
-    fpositer = ufieldpositer_open(&status);
-    ASSERT(U_SUCCESS(status));
-
-    UTF16StringDataNonGCStd resultString;
-    resultString.resize(32);
-    auto resultLength = udat_formatForFields(udat, x, (UChar*)resultString.data(), resultString.size(), fpositer, &status);
-    resultString.resize(resultLength);
-
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        udat_formatForFields(udat, x, (UChar*)resultString.data(), resultLength, fpositer, &status);
-    }
-
-    struct FieldItem {
-        int32_t start;
-        int32_t end;
-        int32_t type;
-    };
-
-    std::vector<FieldItem> fields;
-    while (true) {
-        int32_t start;
-        int32_t end;
-        int32_t type = ufieldpositer_next(fpositer, &start, &end);
-        if (type < 0) {
-            break;
-        }
-
-        FieldItem item;
-        item.start = start;
-        item.end = end;
-        item.type = type;
-
-        fields.push_back(item);
-    }
-
-    ufieldpositer_close(fpositer);
-
-    // add literal field if needs
-    std::vector<FieldItem> literalFields;
-    for (size_t i = 0; i < resultString.length(); i++) {
-        bool found = false;
-        for (size_t j = 0; j < fields.size(); j++) {
-            if ((size_t)fields[j].start <= i && i < (size_t)fields[j].end) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            size_t end = i + 1;
-            while (end != resultString.length()) {
-                bool found = false;
-                for (size_t j = 0; j < fields.size(); j++) {
-                    if ((size_t)fields[j].start <= end && end < (size_t)fields[j].end) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (found) {
-                    break;
-                }
-                end++;
-            }
-
-            FieldItem newItem;
-            newItem.type = -1;
-            newItem.start = i;
-            newItem.end = end;
-            i = end - 1;
-            literalFields.push_back(newItem);
-        }
-    }
-    fields.insert(fields.end(), literalFields.begin(), literalFields.end());
-
-    std::sort(fields.begin(), fields.end(),
-              [](const FieldItem& a, const FieldItem& b) -> bool {
-                  return a.start < b.start;
-              });
-
-    AtomicString typeAtom(state, "type", 4);
-    AtomicString valueAtom = state.context()->staticStrings().value;
-
-    for (size_t i = 0; i < fields.size(); i++) {
-        const FieldItem& item = fields[i];
-
-        Object* o = new Object(state);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(icuFieldTypeToPartName(state, item.type), ObjectPropertyDescriptor::AllPresent));
-        auto sub = resultString.substr(item.start, item.end - item.start);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
-
-        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
-    }
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format date value");
-    }
-
-    return result;
-}
-
-Value IntlDateTimeFormat::toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults)
-{
-    // If options is undefined, then let options be null, else let options be ToObject(options).
-    if (options.isUndefined()) {
-        options = Value(Value::Null);
-    } else {
-        options = options.toObject(state);
-    }
-    // Let create be the standard built-in function object defined in ES5, 15.2.3.5.
-    // Let options be the result of calling the [[Call]] internal method of create with undefined as the this value
-    // and an argument list containing the single item options.
-    options = Object::call(state, state.context()->globalObject()->objectCreate(), Value(), 1, &options);
-
-    // Let needDefaults be true.
-    bool needDefaults = true;
-    // If required is "date" or "any", then
-    if (required.equalsTo(state, state.context()->staticStrings().lazyDate().string()) || required.equalsTo(state, state.context()->staticStrings().lazyAny().string())) {
-        // For each of the property names "weekday", "year", "month", "day":
-        // If the result of calling the [[Get]] internal method of options with the property name is not undefined, then let needDefaults be false.
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyWeekday(), needDefaults);
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyYear(), needDefaults);
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyMonth(), needDefaults);
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyDay(), needDefaults);
-    }
-    // If required is "time" or "any", then
-    if (required.equalsTo(state, state.context()->staticStrings().lazyTime().string()) || required.equalsTo(state, state.context()->staticStrings().lazyAny().string())) {
-        // For each of the property names "hour", "minute", "second":
-        // If the result of calling the [[Get]] internal method of options with the property name is not undefined, then let needDefaults be false.
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyHour(), needDefaults);
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyMinute(), needDefaults);
-        toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazySecond(), needDefaults);
-    }
-
-    // If needDefaults is true and defaults is either "date" or "all", then
-    if (needDefaults && (defaults.equalsTo(state, state.context()->staticStrings().lazyDate().string()) || defaults.equalsTo(state, state.context()->staticStrings().all.string()))) {
-        // For each of the property names "year", "month", "day":
-        // Call the [[DefineOwnProperty]] internal method of options with the property name,
-        // Property Descriptor {[[Value]]: "numeric", [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
-        String* v = state.context()->staticStrings().numeric.string();
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-    }
-    // If needDefaults is true and defaults is either "time" or "all", then
-    if (needDefaults && (defaults.equalsTo(state, state.context()->staticStrings().lazyTime().string()) || defaults.equalsTo(state, state.context()->staticStrings().all.string()))) {
-        // For each of the property names "hour", "minute", "second":
-        // Call the [[DefineOwnProperty]] internal method of options with the property name, Property Descriptor {[[Value]]: "numeric", [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
-        String* v = state.context()->staticStrings().numeric.string();
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-        options.asObject()->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent));
-    }
-
-    return options;
-}
-
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlDateTimeFormat.h
deleted file mode 100644 (file)
index 49eda7a..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlDateTimeFormat__
-#define __EscargotIntlDateTimeFormat__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlDateTimeFormat {
-public:
-    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
-    static void initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options);
-    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* dateTimeFormat, double x);
-    static ArrayObject* formatToParts(ExecutionState& state, Object* dateTimeFormat, double x);
-    static Value toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults);
-};
-
-} // namespace Escargot
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.cpp
deleted file mode 100644 (file)
index ff0efa6..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlLocale.h"
-
-namespace Escargot {
-
-static Intl::CanonicalizedLangunageTag applyOptionsToTag(ExecutionState& state, String* tag, Optional<Object*> options)
-{
-    // we should not allow grandfathered tag like `i-default`(invalid lang), `no-bok`(have extlang)
-    auto u8Tag = tag->toNonGCUTF8StringData();
-    auto tagPart = split(u8Tag, '-');
-    if ((tagPart.size() > 0 && tagPart[0].length() == 1) || (tagPart.size() > 1 && tagPart[1].length() == 3 && isAllSpecialCharacters(tagPart[1], isASCIIAlpha))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
-    }
-
-    // If IsStructurallyValidLanguageTag(tag) is false, throw a RangeError exception.
-    auto parsedResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(u8Tag);
-    if (!parsedResult.canonicalizedTag) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
-    }
-
-    // We should not allow extlang here
-    if (parsedResult.extLang.size()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
-    }
-
-    String* languageString = state.context()->staticStrings().language.string();
-    // Let language be ? GetOption(options, "language", "string", undefined, undefined).
-    Value language = options ? Intl::getOption(state, options.value(), languageString, Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If language is not undefined, then
-    if (!language.isUndefined()) {
-        // If language does not match the unicode_language_subtag production, throw a RangeError exception.
-        auto u8Lang = language.asString()->toNonGCUTF8StringData();
-        UErrorCode status = U_ZERO_ERROR;
-        int32_t len = uloc_forLanguageTag(u8Lang.data(), nullptr, 0, nullptr, &status);
-        UNUSED_VARIABLE(len);
-        if (status != U_BUFFER_OVERFLOW_ERROR || u8Lang.length() != 2 || !isAllSpecialCharacters(u8Lang, isASCIIAlpha)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "lanuage tag you give into Intl.Locale is invalid");
-        }
-    }
-
-    String* scriptString = state.context()->staticStrings().script.string();
-    // Let script be ? GetOption(options, "script", "string", undefined, undefined).
-    Value script = options ? Intl::getOption(state, options.value(), scriptString, Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If script is not undefined, then
-    if (!script.isUndefined()) {
-        // If script does not match the unicode_script_subtag, throw a RangeError exception.
-        String* scriptString = script.asString();
-        if (scriptString->length() != 4 || !scriptString->isAllSpecialCharacters(isASCIIAlpha)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "script you give into Intl.Locale is invalid");
-        }
-    }
-
-    String* regionString = state.context()->staticStrings().region.string();
-    // Let region be ? GetOption(options, "region", "string", undefined, undefined).
-    Value region = options ? Intl::getOption(state, options.value(), regionString, Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If region is not undefined, then
-    if (!region.isUndefined()) {
-        // If region does not match the unicode_region_subtag, throw a RangeError exception.
-        String* regionString = region.asString();
-        if ((!(regionString->length() == 2 && regionString->isAllSpecialCharacters(isASCIIAlpha)) && !(regionString->length() == 3 && regionString->isAllSpecialCharacters(isASCIIDigit)))) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "region you give into Intl.Locale is invalid");
-        }
-    }
-
-    // Let tag to CanonicalizeUnicodeLocaleId(tag).
-    // If language is not undefined,
-    // Assert: tag matches the unicode_locale_id production.
-    // Set tag to tag with the substring corresponding to the unicode_language_subtag production of the unicode_language_id replaced by the string language.
-    // If script is not undefined, then
-    // If tag does not contain a unicode_script_subtag production of the unicode_language_id, then
-    // Set tag to the concatenation of the unicode_language_subtag production of the unicode_languge_id of tag, "-", script, and the rest of tag.
-    // Else,
-    // Set tag to tag with the substring corresponding to the unicode_script_subtag production of the unicode_language_id replaced by the string script.
-    // If region is not undefined, then
-    // If tag does not contain a unicode_region_subtag production of the unicode_language_id, then
-    // Set tag to the concatenation of the unicode_language_subtag production of the unicode_language_id of tag, the substring corresponding to the "-" unicode_script_subtag production of the unicode_language_id if present, "-", region, and the rest of tag.
-    // Else,
-    // Set tag to tag with the substring corresponding to the unicode_region_subtag production of the unicode_language_id replaced by the string region.
-    // Return CanonicalizeUnicodeLocaleId(tag).
-    std::string localeStr;
-
-    if (!language.isUndefined()) {
-        localeStr = language.asString()->toNonGCUTF8StringData();
-    } else {
-        localeStr = parsedResult.language;
-    }
-
-    if (!script.isUndefined()) {
-        localeStr += "-";
-        localeStr += script.asString()->toNonGCUTF8StringData();
-    } else if (parsedResult.script.length()) {
-        localeStr += "-";
-        localeStr += parsedResult.script;
-    }
-
-    if (!region.isUndefined()) {
-        localeStr += "-";
-        localeStr += region.asString()->toNonGCUTF8StringData();
-    } else if (parsedResult.region.length()) {
-        localeStr += "-";
-        localeStr += parsedResult.region;
-    }
-
-    for (size_t i = 0; i < parsedResult.variant.size(); i++) {
-        localeStr += "-";
-        localeStr += parsedResult.variant[i];
-    }
-
-    auto newParsedResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(localeStr);
-    if (!newParsedResult.canonicalizedTag) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Incorrect locale information provided");
-    }
-
-    // We should not allow extlang here
-    if (newParsedResult.extLang.size()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "First argument of Intl.Locale should have valid tag");
-    }
-
-    newParsedResult.privateUse = parsedResult.privateUse;
-    newParsedResult.extensions = parsedResult.extensions;
-    newParsedResult.unicodeExtension = parsedResult.unicodeExtension;
-
-    return newParsedResult;
-}
-
-static bool checkOptionValueIsAlphaNum38DashAlphaNum38(const std::string& value)
-{
-    if (value.length() == 0) {
-        return false;
-    }
-
-    auto parts = split(value, '-');
-    if (parts.size() > 2) {
-        return false;
-    }
-    for (size_t i = 0; i < parts.size(); i++) {
-        const auto& s = parts[i];
-        if (s.length() < 3 || s.length() > 8 || !isAllSpecialCharacters(s, isASCIIAlphanumeric)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-IntlLocaleObject::IntlLocaleObject(ExecutionState& state, String* tag, Optional<Object*> options)
-    : IntlLocaleObject(state, state.context()->globalObject()->intlLocalePrototype(), tag, options)
-{
-}
-
-IntlLocaleObject::IntlLocaleObject(ExecutionState& state, Object* proto, String* tag, Optional<Object*> options)
-    : Object(state, proto)
-{
-    // Set tag to ? ApplyOptionsToTag(tag, options).
-    Intl::CanonicalizedLangunageTag buildResult = applyOptionsToTag(state, tag, options);
-    m_language = String::fromUTF8(buildResult.language.data(), buildResult.language.length());
-    m_script = String::fromUTF8(buildResult.script.data(), buildResult.script.length());
-    m_region = String::fromUTF8(buildResult.region.data(), buildResult.region.length());
-    m_baseName = buildResult.canonicalizedTag.value();
-
-    // Let opt be a new Record.
-    Optional<String*> ca;
-    Optional<String*> co;
-    Optional<String*> hc;
-    Optional<String*> nu;
-    Optional<String*> kf;
-    Optional<String*> kn;
-
-    auto& parsedUnicodeExtension = buildResult.unicodeExtension;
-    for (size_t i = 0; i < parsedUnicodeExtension.size(); i++) {
-        if (!ca && parsedUnicodeExtension[i].first == "ca") {
-            ca = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        } else if (!co && parsedUnicodeExtension[i].first == "co") {
-            co = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        } else if (!hc && parsedUnicodeExtension[i].first == "hc") {
-            hc = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        } else if (!kf && parsedUnicodeExtension[i].first == "kf") {
-            kf = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        } else if (!kn && parsedUnicodeExtension[i].first == "kn") {
-            kn = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        } else if (!nu && parsedUnicodeExtension[i].first == "nu") {
-            nu = String::fromUTF8(parsedUnicodeExtension[i].second.data(), parsedUnicodeExtension[i].second.length());
-        }
-    }
-
-    // Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined).
-    String* calendarString = state.context()->staticStrings().calendar.string();
-    Value calendar = options ? Intl::getOption(state, options.value(), calendarString, Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If calendar is not undefined, then
-    if (!calendar.isUndefined()) {
-        // If calendar does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
-        // If calendar does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
-        std::string value = calendar.asString()->toNonGCUTF8StringData();
-        if (!uloc_toLegacyType("calendar", value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`calendar` option you input is not valid");
-        }
-        // Set opt.[[ca]] to calendar.
-        ca = calendar.asString();
-    }
-
-    // Let collation be ? GetOption(options, "collation", "string", undefined, undefined).
-    Value collation = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().collation.string(), Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If collation is not undefined, then
-    if (!collation.isUndefined()) {
-        // If collation does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
-        // If collation does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
-        std::string value = collation.asString()->toNonGCUTF8StringData();
-        if (!uloc_toLegacyType("collation", value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`collation` option you input is not valid");
-        }
-        // Set opt.[[co]] to collation.
-        co = collation.asString();
-    }
-
-
-    // Let hc be ? GetOption(options, "hourCycle", "string", « "h11", "h12", "h23", "h24" », undefined).
-    Value hourCycleValues[4] = { state.context()->staticStrings().lazyH11().string(), state.context()->staticStrings().lazyH12().string(), state.context()->staticStrings().lazyH23().string(), state.context()->staticStrings().lazyH24().string() };
-    Value hourCycle = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().hourCycle.string(), Intl::StringValue, hourCycleValues, 4, Value()) : Value();
-    // Set opt.[[hc]] to hc.
-    if (!hourCycle.isUndefined()) {
-        hc = hourCycle.asString();
-    }
-
-    // Let kf be ? GetOption(options, "caseFirst", "string", « "upper", "lower", "false" », undefined).
-    Value caseFirstValues[3] = { state.context()->staticStrings().lazyUpper().string(), state.context()->staticStrings().lazyLower().string(), state.context()->staticStrings().stringFalse.string() };
-    // Set opt.[[kf]] to kf.
-    Value caseFirst = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().caseFirst.string(), Intl::StringValue, caseFirstValues, 3, Value()) : Value();
-    if (!caseFirst.isUndefined()) {
-        kf = caseFirst.asString();
-    }
-
-    // Let kn be ? GetOption(options, "numeric", "boolean", undefined, undefined).
-    Value numeric = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().numeric.string(), Intl::BooleanValue, nullptr, 0, Value()) : Value();
-    // If kn is not undefined, set kn to ! ToString(kn).
-    if (!numeric.isUndefined()) {
-        kn = numeric.toString(state);
-    }
-    // Set opt.[[kn]] to kn.
-
-    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
-    Value numberingSystem = options ? Intl::getOption(state, options.value(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value()) : Value();
-    // If numberingSystem is not undefined, then
-    if (!numberingSystem.isUndefined()) {
-        // If numberingSystem does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
-        // If numberingSystem does not match the [(3*8alphanum) *("-" (3*8alphanum))] sequence, throw a RangeError exception.
-        std::string value = numberingSystem.asString()->toNonGCUTF8StringData();
-        if (!uloc_toLegacyType(uloc_toLegacyKey("nu"), value.data()) || !checkOptionValueIsAlphaNum38DashAlphaNum38(value)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "`collation` option you input is not valid");
-        }
-        // Set opt.[[nu]] to numberingSystem.
-        nu = numberingSystem.asString();
-    }
-
-    // Let r be ! ApplyUnicodeExtensionToTag(tag, opt, relevantExtensionKeys).
-    m_calendar = ca;
-    m_caseFirst = kf;
-    m_collation = co;
-    m_hourCycle = hc;
-    m_numberingSystem = nu;
-    m_numeric = kn;
-
-    std::vector<std::pair<std::string, std::string>> newUnicodeExtension;
-    for (size_t i = 0; i < parsedUnicodeExtension.size(); i++) {
-        if (parsedUnicodeExtension[i].first != "ca" && parsedUnicodeExtension[i].first != "co" && parsedUnicodeExtension[i].first != "hc" && parsedUnicodeExtension[i].first != "kf" && parsedUnicodeExtension[i].first != "kn" && parsedUnicodeExtension[i].first != "nu") {
-            newUnicodeExtension.push_back(parsedUnicodeExtension[i]);
-        }
-    }
-
-    if (m_calendar) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("ca"), m_calendar->asString()->toNonGCUTF8StringData()));
-    }
-
-    if (m_caseFirst) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("kf"), m_caseFirst->asString()->equals("true") ? std::string() : m_caseFirst->asString()->toNonGCUTF8StringData()));
-    }
-
-    if (m_collation) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("co"), m_collation->asString()->toNonGCUTF8StringData()));
-    }
-
-    if (m_hourCycle) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("hc"), m_hourCycle->asString()->toNonGCUTF8StringData()));
-    }
-
-    if (m_numberingSystem) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("nu"), m_numberingSystem->asString()->toNonGCUTF8StringData()));
-    }
-
-    if (m_numeric) {
-        newUnicodeExtension.push_back(std::make_pair(std::string("kn"), m_numeric->asString()->equals("true") ? std::string() : m_numeric->asString()->toNonGCUTF8StringData()));
-    }
-
-    std::sort(newUnicodeExtension.begin(), newUnicodeExtension.end(),
-              [](const std::pair<std::string, std::string>& a, const std::pair<std::string, std::string>& b) -> bool {
-                  return a.first < b.first;
-              });
-
-    StringBuilder localeBuilder;
-
-    localeBuilder.appendString(m_baseName);
-
-    size_t extensionIndex;
-    for (extensionIndex = 0; extensionIndex < buildResult.extensions.size(); extensionIndex++) {
-        if (buildResult.extensions[extensionIndex].key == 'u') {
-            extensionIndex++;
-            break;
-        }
-
-        localeBuilder.appendChar('-');
-        localeBuilder.appendChar(buildResult.extensions[extensionIndex].key);
-        localeBuilder.appendChar('-');
-        localeBuilder.appendString(buildResult.extensions[extensionIndex].value.data());
-    }
-
-    if (newUnicodeExtension.size()) {
-        localeBuilder.appendChar('-');
-        localeBuilder.appendChar('u');
-
-        for (size_t i = 0; i < newUnicodeExtension.size(); i++) {
-            if (newUnicodeExtension[i].first.length()) {
-                localeBuilder.appendChar('-');
-                localeBuilder.appendString(newUnicodeExtension[i].first.data());
-            }
-
-            if (newUnicodeExtension[i].second.length()) {
-                localeBuilder.appendChar('-');
-                localeBuilder.appendString(newUnicodeExtension[i].second.data());
-            }
-        }
-    }
-
-    for (; extensionIndex < buildResult.extensions.size(); extensionIndex++) {
-        localeBuilder.appendChar('-');
-        localeBuilder.appendChar(buildResult.extensions[extensionIndex].key);
-        localeBuilder.appendChar('-');
-        localeBuilder.appendString(buildResult.extensions[extensionIndex].value.data());
-    }
-
-    if (buildResult.privateUse.length()) {
-        localeBuilder.appendChar('-');
-        localeBuilder.appendString(buildResult.privateUse.data());
-    }
-
-    m_locale = localeBuilder.finalize();
-}
-
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlLocale.h
deleted file mode 100644 (file)
index dca3eb5..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlLocale__
-#define __EscargotIntlLocale__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlLocaleObject : public Object {
-public:
-    IntlLocaleObject(ExecutionState& state, String* tag, Optional<Object*> options);
-    IntlLocaleObject(ExecutionState& state, Object* proto, String* tag, Optional<Object*> options);
-
-    String* locale() const
-    {
-        return m_locale;
-    }
-
-    String* language() const
-    {
-        return m_language;
-    }
-
-    Value region() const
-    {
-        return m_region->length() ? Value(m_region) : Value();
-    }
-
-    Value script() const
-    {
-        return m_script->length() ? Value(m_script) : Value();
-    }
-
-    String* baseName() const
-    {
-        return m_baseName;
-    }
-
-    Optional<String*> calendar() const
-    {
-        return m_calendar;
-    }
-
-    Optional<String*> caseFirst() const
-    {
-        return m_caseFirst;
-    }
-
-    Optional<String*> collation() const
-    {
-        return m_collation;
-    }
-
-    Optional<String*> hourCycle() const
-    {
-        return m_hourCycle;
-    }
-
-    Optional<String*> numeric() const
-    {
-        return m_numeric;
-    }
-
-    Optional<String*> numberingSystem() const
-    {
-        return m_numberingSystem;
-    }
-
-    virtual bool isIntlLocaleObject() const override
-    {
-        return true;
-    }
-
-protected:
-    String* m_language;
-    String* m_script;
-    String* m_region;
-    String* m_baseName;
-    String* m_locale;
-    Optional<String*> m_calendar; // ca
-    Optional<String*> m_caseFirst; // kf
-    Optional<String*> m_collation; // co
-    Optional<String*> m_hourCycle; // hc
-    Optional<String*> m_numeric; // kn
-    Optional<String*> m_numberingSystem; // nu
-};
-
-} // namespace Escargot
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.cpp
deleted file mode 100644 (file)
index 6e96d0b..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlNumberFormat.h"
-#include "ArrayObject.h"
-#include "VMInstance.h"
-
-namespace Escargot {
-
-static const char* const intlNumberFormatRelevantExtensionKeys[1] = { "nu" };
-static const int intlNumberFormatRelevantExtensionKeysLength = 1;
-
-static size_t currencyDigits(String* currency)
-{
-    // https://www.currency-iso.org/en/home/tables/table-a1.html
-    // we should use ucurr_getDefaultFractionDigits but it returns wrong value for some contury
-    if (currency->equals("BHD")) {
-        return 3;
-    } else if (currency->equals("BIF")) {
-        return 0;
-    } else if (currency->equals("CLF")) {
-        return 4;
-    } else if (currency->equals("CLP")) {
-        return 0;
-    } else if (currency->equals("DJF")) {
-        return 0;
-    } else if (currency->equals("GNF")) {
-        return 0;
-    } else if (currency->equals("IQD")) {
-        return 3;
-    } else if (currency->equals("ISK")) {
-        return 0;
-    } else if (currency->equals("JOD")) {
-        return 3;
-    } else if (currency->equals("JPY")) {
-        return 0;
-    } else if (currency->equals("KMF")) {
-        return 0;
-    } else if (currency->equals("KRW")) {
-        return 0;
-    } else if (currency->equals("KWD")) {
-        return 3;
-    } else if (currency->equals("LYD")) {
-        return 3;
-    } else if (currency->equals("OMR")) {
-        return 3;
-    } else if (currency->equals("PYG")) {
-        return 0;
-    } else if (currency->equals("RWF")) {
-        return 0;
-    } else if (currency->equals("TND")) {
-        return 3;
-    } else if (currency->equals("UGX")) {
-        return 0;
-    } else if (currency->equals("UYI")) {
-        return 0;
-    } else if (currency->equals("UYW")) {
-        return 4;
-    } else if (currency->equals("VND")) {
-        return 0;
-    } else if (currency->equals("VUV")) {
-        return 0;
-    } else if (currency->equals("XAF")) {
-        return 0;
-    } else if (currency->equals("XOF")) {
-        return 0;
-    } else if (currency->equals("XPF")) {
-        return 0;
-    }
-
-    return 2;
-}
-
-static std::vector<std::string> localeDataNumberFormat(String* locale, size_t keyIndex)
-{
-    return Intl::numberingSystemsForLocale(locale);
-}
-
-static Value defaultNumberOption(ExecutionState& state, Value value, double minimum, double maximum, double fallback)
-{
-    // https://tc39.es/ecma402/#sec-defaultnumberoption
-    // If value is not undefined, then
-    if (!value.isUndefined()) {
-        // Let value be ToNumber(value).
-        double doubleValue = value.toNumber(state);
-        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
-        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
-        }
-        // Return floor(value).
-        return Value(floor(doubleValue));
-    } else {
-        // Else, return fallback.
-        return Value(fallback);
-    }
-}
-
-static double getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, double fallback)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
-
-    // Let value be the result of calling the [[Get]] internal method of options with argument property.
-    Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
-    // If value is not undefined, then
-    if (!value.isUndefined()) {
-        // Let value be ToNumber(value).
-        double doubleValue = value.toNumber(state);
-        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
-        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
-        }
-        // Return floor(value).
-        return floor(doubleValue);
-    } else {
-        // Else return fallback.
-        return fallback;
-    }
-}
-
-
-Object* IntlNumberFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
-{
-    Object* numberFormat = new Object(state, realm->globalObject()->intlNumberFormatPrototype());
-    initialize(state, numberFormat, locales, options);
-    return numberFormat;
-}
-
-// https://tc39.es/ecma402/#sec-issanctionedsimpleunitidentifier
-bool isSanctionedSimpleUnitIdentifier(const std::string& s)
-{
-    if (s == "acre") {
-        return true;
-    } else if (s == "bit") {
-        return true;
-    } else if (s == "byte") {
-        return true;
-    } else if (s == "celsius") {
-        return true;
-    } else if (s == "centimeter") {
-        return true;
-    } else if (s == "day") {
-        return true;
-    } else if (s == "degree") {
-        return true;
-    } else if (s == "fahrenheit") {
-        return true;
-    } else if (s == "fluid-ounce") {
-        return true;
-    } else if (s == "foot") {
-        return true;
-    } else if (s == "gallon") {
-        return true;
-    } else if (s == "gigabit") {
-        return true;
-    } else if (s == "gigabyte") {
-        return true;
-    } else if (s == "gram") {
-        return true;
-    } else if (s == "hectare") {
-        return true;
-    } else if (s == "hour") {
-        return true;
-    } else if (s == "inch") {
-        return true;
-    } else if (s == "kilobit") {
-        return true;
-    } else if (s == "kilobyte") {
-        return true;
-    } else if (s == "kilogram") {
-        return true;
-    } else if (s == "kilometer") {
-        return true;
-    } else if (s == "liter") {
-        return true;
-    } else if (s == "megabit") {
-        return true;
-    } else if (s == "megabyte") {
-        return true;
-    } else if (s == "meter") {
-        return true;
-    } else if (s == "mile") {
-        return true;
-    } else if (s == "mile-scandinavian") {
-        return true;
-    } else if (s == "milliliter") {
-        return true;
-    } else if (s == "millimeter") {
-        return true;
-    } else if (s == "millisecond") {
-        return true;
-    } else if (s == "minute") {
-        return true;
-    } else if (s == "month") {
-        return true;
-    } else if (s == "ounce") {
-        return true;
-    } else if (s == "percent") {
-        return true;
-    } else if (s == "petabyte") {
-        return true;
-    } else if (s == "pound") {
-        return true;
-    } else if (s == "second") {
-        return true;
-    } else if (s == "stone") {
-        return true;
-    } else if (s == "terabit") {
-        return true;
-    } else if (s == "terabyte") {
-        return true;
-    } else if (s == "week") {
-        return true;
-    } else if (s == "yard") {
-        return true;
-    } else if (s == "year") {
-        return true;
-    }
-    return false;
-}
-
-static bool isWellFormedUnitIdenifier(const std::string& s)
-{
-    // If the result of IsSanctionedSimpleUnitIdentifier(unitIdentifier) is true, then
-    // Return true.
-    if (isSanctionedSimpleUnitIdentifier(s)) {
-        return true;
-    }
-    // If the substring "-per-" does not occur exactly once in unitIdentifier, then
-    // Return false.
-    auto ss = split(s, "-per-");
-    if (ss.size() != 2) {
-        return false;
-    }
-    // Let numerator be the substring of unitIdentifier from the beginning to just before "-per-".
-    // If the result of IsSanctionedSimpleUnitIdentifier(numerator) is false, then
-    // Return false.
-    // Let denominator be the substring of unitIdentifier from just after "-per-" to the end.
-    // If the result of IsSanctionedSimpleUnitIdentifier(denominator) is false, then
-    // Return false.
-    // Return true.
-    return isSanctionedSimpleUnitIdentifier(ss[0]) && isSanctionedSimpleUnitIdentifier(ss[1]);
-}
-
-static const char* findICUUnitTypeFromUnitString(const std::string& s)
-{
-#define COMPARE_ONCE(to, from)                             \
-    if (memcmp(s.data(), #from, sizeof(#from) - 1) == 0) { \
-        return #to;                                        \
-    }
-    if (false) {
-    }
-    // clang-format off
-    COMPARE_ONCE(area, acre)
-    COMPARE_ONCE(digital, bit)
-    COMPARE_ONCE(digital, byte)
-    COMPARE_ONCE(temperature, celsius)
-    COMPARE_ONCE(length, centimeter)
-    COMPARE_ONCE(duration, day)
-    COMPARE_ONCE(angle, degree)
-    COMPARE_ONCE(temperature, fahrenheit)
-    COMPARE_ONCE(volume, fluid-ounce)
-    COMPARE_ONCE(length, foot)
-    COMPARE_ONCE(volume, gallon)
-    COMPARE_ONCE(digital, gigabit)
-    COMPARE_ONCE(digital, gigabyte)
-    COMPARE_ONCE(mass, gram)
-    COMPARE_ONCE(area, hectare)
-    COMPARE_ONCE(duration, hour)
-    COMPARE_ONCE(length, inch)
-    COMPARE_ONCE(digital, kilobit)
-    COMPARE_ONCE(digital, kilobyte)
-    COMPARE_ONCE(mass, kilogram)
-    COMPARE_ONCE(length, kilometer)
-    COMPARE_ONCE(volume, liter)
-    COMPARE_ONCE(digital, megabit)
-    COMPARE_ONCE(digital, megabyte)
-    COMPARE_ONCE(length, meter)
-    COMPARE_ONCE(length, mile)
-    COMPARE_ONCE(length, mile-scandinavian)
-    COMPARE_ONCE(volume, milliliter)
-    COMPARE_ONCE(length, millimeter)
-    COMPARE_ONCE(duration, millisecond)
-    COMPARE_ONCE(duration, minute)
-    COMPARE_ONCE(duration, month)
-    COMPARE_ONCE(mass, ounce)
-    COMPARE_ONCE(concentr, percent)
-    COMPARE_ONCE(digital, petabyte)
-    COMPARE_ONCE(mass, pound)
-    COMPARE_ONCE(duration, second)
-    COMPARE_ONCE(mass, stone)
-    COMPARE_ONCE(digital, terabit)
-    COMPARE_ONCE(digital, terabyte)
-    COMPARE_ONCE(duration, week)
-    COMPARE_ONCE(length, yard)
-    COMPARE_ONCE(duration, year)
-// clang-format on
-#undef COMPARE_ONCE
-    ASSERT_NOT_REACHED();
-
-    return "";
-}
-
-void IntlNumberFormat::initialize(ExecutionState& state, Object* numberFormat, Value locales, Value options)
-{
-#if defined(ENABLE_RUNTIME_ICU_BINDER)
-    UVersionInfo versionArray;
-    u_getVersion(versionArray);
-    if (versionArray[0] < 62) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.NumberFormat needs 62+ version of ICU");
-    }
-#endif
-
-    // If dateTimeFormat has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
-    AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
-    if (numberFormat->hasInternalSlot() && numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
-    }
-
-    // Set the [[initializedIntlObject]] internal property of dateTimeFormat to true.
-    numberFormat->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(state, initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
-
-    // Let requestedLocales be the result of calling the
-    // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-
-    // If options is undefined, then
-    if (options.isUndefined()) {
-        // Let options be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name.
-        options = new Object(state, Object::PrototypeIsNull);
-    } else {
-        // Else
-        // Let options be ToObject(options).
-        options = options.toObject(state);
-    }
-
-    // Let opt be a new Record.
-    StringMap opt;
-    // Let matcher be the result of calling the GetOption abstract operation (defined in 9.2.9) with the arguments options, "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit".
-    // Set opt.[[localeMatcher]] to matcher.
-    Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
-    Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
-    // Set opt.[[localeMatcher]] to matcher.
-    opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
-
-    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
-    Value numberingSystem = Intl::getOption(state, options.asObject(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
-    // If numberingSystem is not undefined, then
-    if (!numberingSystem.isUndefined()) {
-        // If numberingSystem does not match the Unicode Locale Identifier type nonterminal, throw a RangeError exception.
-        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
-        }
-    }
-    // Set opt.[[nu]] to numberingSystem.
-    if (!numberingSystem.isUndefined()) {
-        opt.insert(std::make_pair("nu", numberingSystem.asString()));
-    }
-
-    // Let NumberFormat be the standard built-in object that is the initial value of Intl.NumberFormat.
-    // Let localeData be the value of the [[localeData]] internal property of NumberFormat.
-    // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the [[availableLocales]]
-    // internal property of NumberFormat, requestedLocales, opt, the [[relevantExtensionKeys]] internal property of NumberFormat, and localeData.
-    StringMap r = Intl::resolveLocale(state, state.context()->vmInstance()->intlNumberFormatAvailableLocales(), requestedLocales, opt, intlNumberFormatRelevantExtensionKeys, intlNumberFormatRelevantExtensionKeysLength, localeDataNumberFormat);
-
-    // Set the [[locale]] internal property of numberFormat to the value of r.[[locale]].
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), numberFormat->internalSlot());
-    // Set numberFormat.[[DataLocale]] to r.[[dataLocale]].
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDataLocale()), r.at("dataLocale"), numberFormat->internalSlot());
-    // Set the [[numberingSystem]] internal property of numberFormat to the value of r.[[nu]].
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), r.at("nu"), numberFormat->internalSlot());
-
-    // SetNumberFormatUnitOptions ( intlObj, options )
-    // Let s be the result of calling the GetOption abstract operation with the arguments options, "style", "string",
-    // a List containing the three String values "decimal", "percent", and "currency", and "decimal".
-    Value styleValues[4] = { state.context()->staticStrings().lazyDecimal().string(), state.context()->staticStrings().lazyPercent().string(), state.context()->staticStrings().lazyCurrency().string(), state.context()->staticStrings().lazyUnit().string() };
-    Value style = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyStyle().string(), Intl::StringValue, styleValues, 4, styleValues[0]);
-
-    // Set the [[style]] internal property of numberFormat to s.
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyStyle()), style, numberFormat->internalSlot());
-
-    // Let currency be the result of calling the GetOption abstract operation with the arguments options, "currency", "string", undefined, and undefined.
-    Value currency = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrency().string(), Intl::StringValue, nullptr, 0, Value());
-    // If currency is not undefined and the result of calling the IsWellFormedCurrencyCode abstract operation (defined in 6.3.1) with argument c is false, then throw a RangeError exception.
-    if (!currency.isUndefined()) {
-        String* currencyString = currency.asString();
-        UTF8StringDataNonGCStd cc = currencyString->toUTF8StringData().data();
-        if (currencyString->length() != 3 || !isAllSpecialCharacters(cc, isASCIIAlpha)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "currency is not a well-formed currency code");
-        }
-    }
-
-    // If style is "currency" and currency is undefined, throw a TypeError exception.
-    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string()) && currency.isUndefined()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "if style option is `currency`, you must specify currency");
-    }
-
-    // Let currencyDisplay be ? GetOption(options, "currencyDisplay", "string", « "code", "symbol", "narrowSymbol", "name" », "symbol").
-    Value currencyDisplayValues[4] = { state.context()->staticStrings().lazyCode().string(), state.context()->staticStrings().symbol.string(), state.context()->staticStrings().lazyNarrowSymbol().string(), state.context()->staticStrings().name.string() };
-    Value currencyDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrencyDisplay().string(), Intl::StringValue, currencyDisplayValues, 4, currencyDisplayValues[1]);
-    // Let currencySign be ? GetOption(options, "currencySign", "string", « "standard", "accounting" », "standard").
-    Value currencySignValues[2] = { state.context()->staticStrings().lazyStandard().string(), state.context()->staticStrings().lazyAccounting().string() };
-    Value currencySign = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCurrencySign().string(), Intl::StringValue, currencySignValues, 2, currencySignValues[0]);
-    // Let unit be ? GetOption(options, "unit", "string", undefined, undefined).
-    Value unit = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUnit().string(), Intl::StringValue, nullptr, 0, Value());
-    if (!unit.isUndefined()) {
-        String* unitString = unit.asString();
-        UTF8StringDataNonGCStd cc = unitString->toUTF8StringData().data();
-        if (!isWellFormedUnitIdenifier(cc)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is not a well-formed unit idenitfier");
-        }
-    }
-
-    // If style is "unit" and unit is undefined, throw a TypeError exception.
-    if (style.equalsTo(state, state.context()->staticStrings().lazyUnit().string()) && unit.isUndefined()) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "if style option is `unit`, you must specify unit");
-    }
-
-    // Let unitDisplay be ? GetOption(options, "unitDisplay", "string", « "short", "narrow", "long" », "short").
-    Value unitDisplayValues[3] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyLong().string() };
-    Value unitDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUnitDisplay().string(), Intl::StringValue, unitDisplayValues, 3, unitDisplayValues[0]);
-
-    // If style is "currency", then
-    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
-        // Let currency be the result of converting currency to upper case as specified in 6.1.
-        String* cString = currency.toString(state);
-        std::string str = cString->toUTF8StringData().data();
-        std::transform(str.begin(), str.end(), str.begin(), toupper);
-        currency = String::fromASCII(str.data(), str.length());
-        // Set intlObj.[[Currency]] to currency.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrency()), currency, numberFormat->internalSlot());
-        // Set intlObj.[[CurrencyDisplay]] to currencyDisplay.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrencyDisplay()), currencyDisplay.asString(), numberFormat->internalSlot());
-        // Set intlObj.[[CurrencySign]] to currencySign.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCurrencySign()), currencySign.asString(), numberFormat->internalSlot());
-    }
-
-    // If style is "unit", then
-    if (style.equalsTo(state, state.context()->staticStrings().lazyUnit().string())) {
-        // Set intlObj.[[Unit]] to unit.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUnit()), unit.asString(), numberFormat->internalSlot());
-        // Set intlObj.[[UnitDisplay]] to unitDisplay.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUnitDisplay()), unitDisplay.asString(), numberFormat->internalSlot());
-    }
-
-    double mnfdDefault = 0;
-    double mxfdDefault = 0;
-
-    // Let style be numberFormat.[[Style]].
-    // If style is "currency", then
-    if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
-        // Let currency be numberFormat.[[Currency]].
-        // Let cDigits be CurrencyDigits(currency).
-        size_t cDigits = currencyDigits(currency.asString());
-        // Let mnfdDefault be cDigits.
-        mnfdDefault = cDigits;
-        // Let mxfdDefault be cDigits.
-        mxfdDefault = cDigits;
-    } else {
-        // Else,
-        // Let mnfdDefault be 0.
-        mnfdDefault = 0;
-        // If style is "percent", then
-        if (style.equalsTo(state, state.context()->staticStrings().lazyCurrency().string())) {
-            // Let mxfdDefault be 0.
-            mxfdDefault = 0;
-        } else {
-            // Else,
-            // Let mxfdDefault be 3.
-            mxfdDefault = 3;
-        }
-    }
-
-    // Let notation be ? GetOption(options, "notation", "string", « "standard", "scientific", "engineering", "compact" », "standard").
-    Value notationValues[4] = { state.context()->staticStrings().lazyStandard().string(), state.context()->staticStrings().lazyScientific().string(), state.context()->staticStrings().lazyEngineering().string(), state.context()->staticStrings().lazyCompact().string() };
-    Value notation = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyNotation().string(), Intl::StringValue, notationValues, 4, notationValues[0]);
-    // Set numberFormat.[[Notation]] to notation.
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyNotation()), notation, numberFormat->internalSlot());
-
-    // Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
-    // Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1).
-    double mnid = getNumberOption(state, options.asObject(), state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
-    // Let mnfd be ? Get(options, "minimumFractionDigits").
-    Value mnfd;
-    auto g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()));
-    if (g.hasValue()) {
-        mnfd = g.value(state, options.asObject());
-    }
-    // Let mxfd be ? Get(options, "maximumFractionDigits").
-    Value mxfd;
-    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()));
-    if (g.hasValue()) {
-        mxfd = g.value(state, options.asObject());
-    }
-    // Let mnsd be ? Get(options, "minimumSignificantDigits").
-    Value mnsd;
-    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()));
-    if (g.hasValue()) {
-        mnsd = g.value(state, options.asObject());
-    }
-    // Let mxsd be ? Get(options, "maximumSignificantDigits").
-    Value mxsd;
-    g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()));
-    if (g.hasValue()) {
-        mxsd = g.value(state, options.asObject());
-    }
-
-    // Set intlObj.[[MinimumIntegerDigits]] to mnid.
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits()), Value(mnid), numberFormat->internalSlot());
-
-    // If mnsd is not undefined or mxsd is not undefined, then
-    if (!mnsd.isUndefined() || !mxsd.isUndefined()) {
-        // Set intlObj.[[RoundingType]] to significantDigits.
-        // Let mnsd be ? DefaultNumberOption(mnsd, 1, 21, 1).
-        mnsd = defaultNumberOption(state, mnsd, 1, 21, 1);
-        // Let mxsd be ? DefaultNumberOption(mxsd, mnsd, 21, 21).
-        mxsd = defaultNumberOption(state, mxsd, mnsd.asNumber(), 21, 21);
-        // Set intlObj.[[MinimumSignificantDigits]] to mnsd.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()), mnsd, numberFormat->internalSlot());
-        // Set intlObj.[[MaximumSignificantDigits]] to mxsd.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits()), mxsd, numberFormat->internalSlot());
-    } else if (!mnfd.isUndefined() || !mxfd.isUndefined()) {
-        // Else if mnfd is not undefined or mxfd is not undefined, then
-        // Set intlObj.[[RoundingType]] to fractionDigits.
-        // Let mnfd be ? DefaultNumberOption(mnfd, 0, 20, mnfdDefault).
-        mnfd = defaultNumberOption(state, mnfd, 0, 20, mnfdDefault);
-        // Let mxfdActualDefault be max( mnfd, mxfdDefault ).
-        double mxfdActualDefault = std::max(mnfd.asNumber(), mxfdDefault);
-        // Let mxfd be ? DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault).
-        mxfd = defaultNumberOption(state, mxfd, mnfd.asNumber(), 20, mxfdActualDefault);
-        // Set intlObj.[[MinimumFractionDigits]] to mnfd.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), mnfd, numberFormat->internalSlot());
-        // Set intlObj.[[MaximumFractionDigits]] to mxfd.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), mxfd, numberFormat->internalSlot());
-    } else if (notation.equalsTo(state, state.context()->staticStrings().lazyCompact().string())) {
-        // Else if notation is "compact", then
-        // Set intlObj.[[RoundingType]] to compactRounding.
-    } else {
-        // Set intlObj.[[RoundingType]] to fractionDigits.
-        // Set intlObj.[[MinimumFractionDigits]] to mnfdDefault.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()), Value(mnfdDefault), numberFormat->internalSlot());
-        // Set intlObj.[[MaximumFractionDigits]] to mxfdDefault.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits()), Value(mxfdDefault), numberFormat->internalSlot());
-    }
-
-    // Let compactDisplay be ? GetOption(options, "compactDisplay", "string", « "short", "long" », "short").
-    Value compactDisplayValues[2] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
-    Value compactDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyCompactDisplay().string(), Intl::StringValue, compactDisplayValues, 2, compactDisplayValues[0]);
-
-    // If notation is "compact", then
-    if (notation.equalsTo(state, state.context()->staticStrings().lazyCompact().string())) {
-        // Set numberFormat.[[CompactDisplay]] to compactDisplay.
-        numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyCompactDisplay()), compactDisplay, numberFormat->internalSlot());
-    }
-
-    // Let useGrouping be ? GetOption(options, "useGrouping", "boolean", undefined, true).
-    Value useGrouping = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyUseGrouping().string(), Intl::BooleanValue, nullptr, 0, Value(true));
-    // Set numberFormat.[[UseGrouping]] to useGrouping.
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyUseGrouping()), useGrouping, numberFormat->internalSlot());
-
-    // Let signDisplay be ? GetOption(options, "signDisplay", "string", « "auto", "never", "always", "exceptZero" », "auto").
-    Value signDisplayValue[4] = { state.context()->staticStrings().lazyAuto().string(), state.context()->staticStrings().lazyNever().string(), state.context()->staticStrings().lazyAlways().string(), state.context()->staticStrings().lazyExceptZero().string() };
-    Value signDisplay = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazySignDisplay().string(), Intl::StringValue, signDisplayValue, 4, signDisplayValue[0]);
-    // Set numberFormat.[[SignDisplay]] to signDisplay.
-    numberFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySignDisplay()), signDisplay, numberFormat->internalSlot());
-
-    // Set the [[initializedNumberFormat]] internal property of numberFormat to true.
-    numberFormat->internalSlot()->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedNumberFormat()), ObjectPropertyDescriptor(Value(true)));
-    // Return numberFormat
-
-    UTF16StringDataNonGCStd skeleton;
-
-    if (style.asString()->equals("currency")) {
-        if (!currency.isUndefined()) {
-            skeleton += u"currency/";
-            skeleton += currency.asString()->charAt(0);
-            skeleton += currency.asString()->charAt(1);
-            skeleton += currency.asString()->charAt(2);
-            skeleton += u" ";
-        }
-
-        if (currencyDisplay.asString()->equals("code")) {
-            skeleton += u"unit-width-iso-code ";
-        } else if (currencyDisplay.asString()->equals("symbol")) {
-            // default
-        } else if (currencyDisplay.asString()->equals("narrowSymbol")) {
-            skeleton += u"unit-width-narrow ";
-        } else if (currencyDisplay.asString()->equals("name")) {
-            skeleton += u"unit-width-full-name ";
-        } else {
-            ASSERT_NOT_REACHED();
-        }
-    } else if (style.asString()->equals("percent")) {
-        skeleton += u"percent scale/100 ";
-    } else if (style.asString()->equals("unit")) {
-        String* unitString = unit.asString();
-        if (unitString->contains("-per-")) {
-            size_t pos = unitString->find("-per-");
-            skeleton += u"measure-unit/";
-            const char* u = findICUUnitTypeFromUnitString(unitString->substring(0, pos)->toNonGCUTF8StringData());
-            size_t len = strlen(u);
-            for (size_t i = 0; i < len; i++) {
-                skeleton += u[i];
-            }
-            skeleton += '-';
-            skeleton += unitString->substring(0, pos)->toUTF16StringData().data();
-            skeleton += ' ';
-
-            skeleton += u"per-measure-unit/";
-            u = findICUUnitTypeFromUnitString(unitString->substring(pos + 5, unitString->length())->toNonGCUTF8StringData());
-            len = strlen(u);
-            for (size_t i = 0; i < len; i++) {
-                skeleton += u[i];
-            }
-            skeleton += '-';
-            skeleton += unitString->substring(pos + 5, unitString->length())->toUTF16StringData().data();
-            skeleton += ' ';
-        } else {
-            skeleton += u"measure-unit/";
-            const char* u = findICUUnitTypeFromUnitString(unitString->toNonGCUTF8StringData());
-            size_t len = strlen(u);
-            for (size_t i = 0; i < len; i++) {
-                skeleton += u[i];
-            }
-            skeleton += '-';
-            skeleton += unitString->toUTF16StringData().data();
-            skeleton += ' ';
-        }
-
-        String* unitDisplayString = unitDisplay.asString();
-        if (unitDisplayString->equals("short")) {
-            skeleton += u"unit-width-short ";
-        } else if (unitDisplayString->equals("narrow")) {
-            skeleton += u"unit-width-narrow ";
-        } else {
-            ASSERT(unitDisplayString->equals("long"));
-            skeleton += u"unit-width-full-name ";
-        }
-    }
-
-    if (numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits()))) {
-        double mnsd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
-        double mxsd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
-
-        for (double i = 0; i < mnsd; i++) {
-            skeleton += '@';
-        }
-
-        for (double i = 0; i < mxsd - mnsd; i++) {
-            skeleton += '#';
-        }
-
-        skeleton += ' ';
-    }
-
-    if (numberFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()))) {
-        double mnfd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
-        double mxfd = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumFractionDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
-
-        skeleton += '.';
-
-        for (double i = 0; i < mnfd; i++) {
-            skeleton += '0';
-        }
-
-        for (double i = 0; i < mxfd - mnfd; i++) {
-            skeleton += '#';
-        }
-        skeleton += ' ';
-    }
-
-    {
-        double mnid = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumIntegerDigits())).value(state, numberFormat->internalSlot()).toNumber(state);
-        skeleton += u"integer-width/+";
-        for (double i = 0; i < mnid; i++) {
-            skeleton += '0';
-        }
-        skeleton += ' ';
-    }
-
-    if (!useGrouping.asBoolean()) {
-        skeleton += u"group-off ";
-    }
-
-    String* notationString = notation.asString();
-    if (notationString->equals("standard")) {
-    } else if (notationString->equals("scientific")) {
-        skeleton += u"scientific ";
-    } else if (notationString->equals("engineering")) {
-        skeleton += u"engineering ";
-    } else {
-        if (compactDisplay.asString()->equals("short")) {
-            skeleton += u"compact-short ";
-        } else {
-            skeleton += u"compact-long ";
-        }
-    }
-
-    String* signDisplayString = signDisplay.asString();
-    bool accountingSign = currencySign.asString()->equals("accounting");
-    if (signDisplayString->equals("auto")) {
-        if (accountingSign) {
-            skeleton += u"sign-accounting ";
-        }
-    } else if (signDisplayString->equals("never")) {
-        skeleton += u"sign-never ";
-    } else if (signDisplayString->equals("always")) {
-        if (accountingSign) {
-            skeleton += u"sign-accounting-always ";
-        } else {
-            skeleton += u"sign-always ";
-        }
-    } else {
-        if (accountingSign) {
-            skeleton += u"sign-accounting-except-zero ";
-        } else {
-            skeleton += u"sign-except-zero ";
-        }
-    }
-
-    skeleton += u"rounding-mode-half-up ";
-
-    String* localeOption = numberFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale())).value(state, numberFormat->internalSlot()).toString(state);
-
-    UErrorCode status = U_ZERO_ERROR;
-    UNumberFormatter* fomatter = unumf_openForSkeletonAndLocale((UChar*)skeleton.data(), skeleton.length(), localeOption->toNonGCUTF8StringData().data(), &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init NumberFormat");
-    }
-
-    numberFormat->internalSlot()->setExtraData(fomatter);
-
-    numberFormat->internalSlot()->addFinalizer([](Object* obj, void* data) {
-        Object* self = (Object*)obj;
-        unumf_close((UNumberFormatter*)self->extraData());
-    },
-                                               nullptr);
-}
-
-UTF16StringDataNonGCStd IntlNumberFormat::format(ExecutionState& state, Object* numberFormat, double x)
-{
-    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
-
-    UErrorCode status = U_ZERO_ERROR;
-    UTF16StringDataNonGCStd resultString;
-
-    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
-
-    unumf_formatDouble(formatter, x, uresult.get(), &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    resultString.resize(32);
-    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    resultString.resize(length);
-
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    }
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    return resultString;
-}
-
-UTF16StringDataNonGCStd IntlNumberFormat::format(ExecutionState& state, Object* numberFormat, String* str)
-{
-    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
-
-    UErrorCode status = U_ZERO_ERROR;
-    UTF16StringDataNonGCStd resultString;
-
-    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
-
-    auto s = str->toNonGCUTF8StringData();
-
-    unumf_formatDecimal(formatter, s.data(), s.length(), uresult.get(), &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    resultString.resize(32);
-    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    resultString.resize(length);
-
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    }
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    return resultString;
-}
-
-ArrayObject* IntlNumberFormat::formatToParts(ExecutionState& state, Object* numberFormat, double x)
-{
-    UNumberFormatter* formatter = (UNumberFormatter*)numberFormat->internalSlot()->extraData();
-
-    ArrayObject* result = new ArrayObject(state);
-
-    UErrorCode status = U_ZERO_ERROR;
-    UTF16StringDataNonGCStd resultString;
-
-    LocalResourcePointer<UFormattedNumber> uresult(unumf_openResult(&status), [](UFormattedNumber* f) { unumf_closeResult(f); });
-
-    unumf_formatDouble(formatter, x, uresult.get(), &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    resultString.resize(32);
-    auto length = unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    resultString.resize(length);
-
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        status = U_ZERO_ERROR;
-        unumf_resultToString(uresult.get(), (UChar*)resultString.data(), resultString.size(), &status);
-    }
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    LocalResourcePointer<UFieldPositionIterator> fpositer(ufieldpositer_open(&status), [](UFieldPositionIterator* f) { ufieldpositer_close(f); });
-    ASSERT(U_SUCCESS(status));
-
-    unumf_resultGetAllFieldPositions(uresult.get(), fpositer.get(), &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to format a number");
-    }
-
-    std::vector<Intl::NumberFieldItem> fields;
-
-    while (true) {
-        int32_t start;
-        int32_t end;
-        int32_t type = ufieldpositer_next(fpositer.get(), &start, &end);
-        if (type < 0) {
-            break;
-        }
-
-        if (std::isnan(x) || std::isinf(x)) {
-            // We should ignore `E0` field of NaN, Infinity
-            // NaNE0->NaN
-            if (type == UNUM_EXPONENT_SYMBOL_FIELD) {
-                continue;
-            }
-            if (type == UNUM_EXPONENT_FIELD) {
-                continue;
-            }
-        }
-
-        Intl::NumberFieldItem item;
-        item.start = start;
-        item.end = end;
-        item.type = type;
-
-        fields.push_back(item);
-    }
-
-    Intl::convertICUNumberFieldToEcmaNumberField(fields, x, resultString);
-
-    AtomicString typeAtom(state, "type", 4);
-    AtomicString valueAtom = state.context()->staticStrings().value;
-
-    for (size_t i = 0; i < fields.size(); i++) {
-        const Intl::NumberFieldItem& item = fields[i];
-
-        Object* o = new Object(state);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(Intl::icuNumberFieldToString(state, item.type, x), ObjectPropertyDescriptor::AllPresent));
-        auto sub = resultString.substr(item.start, item.end - item.start);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
-
-        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
-    }
-
-    return result;
-}
-
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlNumberFormat.h
deleted file mode 100644 (file)
index 37fb841..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2019-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlNumberFormat__
-#define __EscargotIntlNumberFormat__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlNumberFormat {
-public:
-    static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
-    static void initialize(ExecutionState& state, Object* numberFormat, Value locales, Value options);
-    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* numberFormat, double x);
-    static UTF16StringDataNonGCStd format(ExecutionState& state, Object* numberFormat, String* str);
-    static ArrayObject* formatToParts(ExecutionState& state, Object* numberFormat, double x);
-};
-
-} // namespace Escargot
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.cpp
deleted file mode 100644 (file)
index 11571b5..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlPluralRules.h"
-#include "VMInstance.h"
-
-namespace Escargot {
-
-static double getNumberOption(ExecutionState& state, Optional<Object*> options, String* property, double minimum, double maximum, double fallback)
-{
-    // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
-    if (!options) {
-        return fallback;
-    }
-
-    // Let value be the result of calling the [[Get]] internal method of options with argument property.
-    Value value = options.value()->get(state, ObjectPropertyName(state, property)).value(state, options.value());
-    // If value is not undefined, then
-    if (!value.isUndefined()) {
-        // Let value be ToNumber(value).
-        double doubleValue = value.toNumber(state);
-        // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
-        if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
-        }
-        // Return floor(value).
-        return floor(doubleValue);
-    } else {
-        // Else return fallback.
-        return fallback;
-    }
-}
-
-void* IntlPluralRulesObject::operator new(size_t size)
-{
-    static MAY_THREAD_LOCAL bool typeInited = false;
-    static MAY_THREAD_LOCAL GC_descr descr;
-    if (!typeInited) {
-        GC_word desc[GC_BITMAP_SIZE(IntlPluralRulesObject)] = { 0 };
-        Object::fillGCDescriptor(desc);
-        GC_set_bit(desc, GC_WORD_OFFSET(IntlPluralRulesObject, m_locale));
-        GC_set_bit(desc, GC_WORD_OFFSET(IntlPluralRulesObject, m_type));
-        descr = GC_make_descriptor(desc, GC_WORD_LEN(IntlPluralRulesObject));
-        typeInited = true;
-    }
-    return GC_MALLOC_EXPLICITLY_TYPED(size, descr);
-}
-
-IntlPluralRulesObject::IntlPluralRulesObject(ExecutionState& state, Object* proto, Value locales, Value options)
-    : Object(state, proto)
-    , m_icuPluralRules(nullptr)
-    , m_icuNumberFormat(nullptr)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-initializepluralrules
-    // [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]], [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]
-
-    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-
-    Optional<Object*> optionObject;
-    // If options is undefined, then
-    if (options.isUndefined()) {
-        // Let options be ObjectCreate(null).
-    } else {
-        // Let options be ? ToObject(options).
-        optionObject = options.toObject(state);
-    }
-
-    // Let opt be a new Record.
-    StringMap opt;
-    // Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
-    // Set opt.[[localeMatcher]] to matcher.
-    Value localeMatcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
-    String* matcher = localeMatcherValues[1].asString();
-    if (optionObject) {
-        matcher = Intl::getOption(state, optionObject.value(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, localeMatcherValues, 2, localeMatcherValues[1]).asString();
-    }
-    opt.insert(std::make_pair("matcher", matcher));
-
-    // Let t be ? GetOption(options, "type", "string", « "cardinal", "ordinal" », "cardinal").
-    Value typeValues[2] = { state.context()->staticStrings().lazyCardinal().string(), state.context()->staticStrings().lazyOrdinal().string() };
-    String* t = typeValues[0].asString();
-    if (optionObject) {
-        t = Intl::getOption(state, optionObject.value(), state.context()->staticStrings().lazyType().string(), Intl::StringValue, typeValues, 2, typeValues[0]).asString();
-    }
-
-    // Perform ? SetNumberFormatDigitOptions(pluralRules, options, 0, 3).
-    // Let mnid be the result of calling the GetNumberOption abstract operation (defined in 9.2.10) with arguments options, "minimumIntegerDigits", 1, 21, and 1.
-    double mnid = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
-    // Set the [[minimumIntegerDigits]] internal property of numberFormat to mnid.
-    m_minimumIntegerDigits = mnid;
-
-    double mnfdDefault = 0;
-    // Let mnfd be the result of calling the GetNumberOption abstract operation with arguments options, "minimumFractionDigits", 0, 20, and mnfdDefault.
-    double mnfd = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMinimumFractionDigits().string(), 0, 20, mnfdDefault);
-
-    // Set the [[minimumFractionDigits]] internal property of numberFormat to mnfd.
-    m_minimumFractionDigits = mnfd;
-
-    double mxfdDefault = 3;
-
-    // Let mxfd be the result of calling the GetNumberOption abstract operation with arguments options, "maximumFractionDigits", mnfd, 20, and mxfdDefault.
-    double mxfd = getNumberOption(state, optionObject, state.context()->staticStrings().lazyMaximumFractionDigits().string(), mnfd, 20, mxfdDefault);
-
-    // Set the [[maximumFractionDigits]] internal property of numberFormat to mxfd.
-    m_maximumFractionDigits = mxfd;
-
-    if (optionObject) {
-        // Let mnsd be the result of calling the [[Get]] internal method of options with argument "minimumSignificantDigits".
-        Value mnsd = optionObject.value()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumSignificantDigits())).value(state, optionObject.value());
-        // Let mxsd be the result of calling the [[Get]] internal method of options with argument "maximumSignificantDigits".
-        Value mxsd = optionObject.value()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMaximumSignificantDigits())).value(state, optionObject.value());
-
-        // If mnsd is not undefined or mxsd is not undefined, then:
-        if (!mnsd.isUndefined() || !mxsd.isUndefined()) {
-            // Let mnsd be the result of calling the GetNumberOption abstract operation with arguments options, "minimumSignificantDigits", 1, 21, and 1.
-            mnsd = Value(getNumberOption(state, optionObject.value(), state.context()->staticStrings().lazyMinimumSignificantDigits().string(), 1, 21, 1));
-            // Let mxsd be the result of calling the GetNumberOption abstract operation with arguments options, "maximumSignificantDigits", mnsd, 21, and 21.
-            mxsd = Value(getNumberOption(state, optionObject.value(), state.context()->staticStrings().lazyMaximumSignificantDigits().string(), mnsd.asNumber(), 21, 21));
-            // Set the [[minimumSignificantDigits]] internal property of numberFormat to mnsd,
-            // and the [[maximumSignificantDigits]] internal property of numberFormat to mxsd.
-            m_minimumSignificantDigits = mnsd.asNumber();
-            m_maximumSignificantDigits = mxsd.asNumber();
-        }
-    }
-
-    // Let localeData be %PluralRules%.[[LocaleData]].
-    // Let r be ResolveLocale(%PluralRules%.[[AvailableLocales]], requestedLocales, opt, %PluralRules%.[[RelevantExtensionKeys]], localeData).
-    // Set pluralRules.[[Locale]] to the value of r.[[locale]].
-    auto r = Intl::resolveLocale(state, state.context()->vmInstance()->intlPluralRulesAvailableLocales(), requestedLocales, opt, nullptr, 0, nullptr);
-    String* foundLocale = r.at("locale");
-
-    UErrorCode status = U_ZERO_ERROR;
-    m_icuNumberFormat = unum_open(UNUM_DEFAULT, nullptr, 0, foundLocale->toNonGCUTF8StringData().data(), nullptr, &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init PluralRule");
-    }
-
-    if (!m_minimumSignificantDigits.hasValue()) {
-        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits);
-        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits);
-        unum_setAttribute(m_icuNumberFormat, UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits);
-    } else {
-        unum_setAttribute(m_icuNumberFormat, UNUM_SIGNIFICANT_DIGITS_USED, true);
-        unum_setAttribute(m_icuNumberFormat, UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits);
-        unum_setAttribute(m_icuNumberFormat, UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits);
-    }
-    unum_setAttribute(m_icuNumberFormat, UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Failed to init NumberFormat");
-    }
-
-    ASSERT(U_SUCCESS(status));
-
-    UPluralType icuType = UPLURAL_TYPE_CARDINAL;
-    if (t->equals("ordinal")) {
-        icuType = UPLURAL_TYPE_ORDINAL;
-    }
-
-    m_icuPluralRules = uplrules_openForType(foundLocale->toNonGCUTF8StringData().data(), icuType, &status);
-    if (!m_icuPluralRules) {
-        auto parseResult = Intl::isStructurallyValidLanguageTagAndCanonicalizeLanguageTag(foundLocale->toNonGCUTF8StringData());
-        // Remove extensions and try again.
-        m_icuPluralRules = uplrules_openForType(parseResult.language.data(), icuType, &status);
-        ASSERT(U_SUCCESS(status));
-    }
-
-    m_locale = foundLocale;
-    m_type = t;
-
-    addFinalizer([](Object* obj, void* data) {
-        IntlPluralRulesObject* self = (IntlPluralRulesObject*)obj;
-        uplrules_close(self->m_icuPluralRules);
-        unum_close(self->m_icuNumberFormat);
-    },
-                 nullptr);
-
-    // Return pluralRules.
-}
-
-String* IntlPluralRulesObject::resolvePlural(double number)
-{
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-resolveplural
-    // If n is not a finite Number, then
-    if (std::isinf(number)) {
-        // Return "other".
-        return String::fromASCII("other");
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    int32_t len = uplrules_selectWithFormat(m_icuPluralRules, number, m_icuNumberFormat, nullptr, 0, &status);
-    UChar* buf = (UChar*)alloca((len + 1) * sizeof(UChar));
-    status = U_ZERO_ERROR;
-    uplrules_selectWithFormat(m_icuPluralRules, number, m_icuNumberFormat, buf, len + 1, &status);
-    ASSERT(U_SUCCESS(status));
-
-    return new UTF16String(buf, len);
-}
-
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlPluralRules.h
deleted file mode 100644 (file)
index 99cb8eb..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlPluralRules__
-#define __EscargotIntlPluralRules__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlPluralRulesObject : public Object {
-public:
-    // https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl-pluralrules-constructor
-    IntlPluralRulesObject(ExecutionState& state, Object* proto, Value locales, Value options);
-
-    virtual bool isIntlPluralRulesObject() const override
-    {
-        return true;
-    }
-
-    String* resolvePlural(double number);
-
-    String* locale() const
-    {
-        return m_locale;
-    }
-
-    String* type() const
-    {
-        return m_type;
-    }
-
-    double minimumIntegerDigits() const
-    {
-        return m_minimumIntegerDigits;
-    }
-
-    double minimumFractionDigits() const
-    {
-        return m_minimumFractionDigits;
-    }
-
-    double maximumFractionDigits() const
-    {
-        return m_maximumFractionDigits;
-    }
-
-    Optional<double> minimumSignificantDigits() const
-    {
-        return m_minimumSignificantDigits;
-    }
-
-    Optional<double> maximumSignificantDigits() const
-    {
-        return m_maximumSignificantDigits;
-    }
-
-    UPluralRules* icuPluralRules() const
-    {
-        return m_icuPluralRules;
-    }
-
-    UNumberFormat* icuNumberFormat() const
-    {
-        return m_icuNumberFormat;
-    }
-
-    void* operator new(size_t size);
-    void* operator new[](size_t size) = delete;
-
-protected:
-    String* m_locale;
-    String* m_type;
-    double m_minimumIntegerDigits;
-    double m_minimumFractionDigits;
-    double m_maximumFractionDigits;
-    Optional<double> m_minimumSignificantDigits;
-    Optional<double> m_maximumSignificantDigits;
-
-    UPluralRules* m_icuPluralRules;
-    UNumberFormat* m_icuNumberFormat;
-};
-
-} // namespace Escargot
-#endif
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.cpp
deleted file mode 100644 (file)
index e4336d5..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-#include "Escargot.h"
-#include "Context.h"
-#include "ExecutionState.h"
-#include "Value.h"
-#include "Intl.h"
-#include "IntlRelativeTimeFormat.h"
-#include "DateObject.h"
-#include "ArrayObject.h"
-#include "VMInstance.h"
-
-namespace Escargot {
-
-static const char* const intlRelativeTimeFormatRelevantExtensionKeys[1] = { "nu" };
-static size_t intlRelativeTimeFormatRelevantExtensionKeysLength = 1;
-static const size_t indexOfExtensionKeyNu = 0;
-
-static std::vector<std::string> localeDataRelativeTimeFormat(String* locale, size_t keyIndex)
-{
-    std::vector<std::string> keyLocaleData;
-    switch (keyIndex) {
-    case indexOfExtensionKeyNu:
-        keyLocaleData = Intl::numberingSystemsForLocale(locale);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    return keyLocaleData;
-}
-
-IntlRelativeTimeFormatObject::IntlRelativeTimeFormatObject(ExecutionState& state, Value locales, Value options)
-    : IntlRelativeTimeFormatObject(state, state.context()->globalObject()->intlRelativeTimeFormatPrototype(), locales, options)
-{
-}
-
-IntlRelativeTimeFormatObject::IntlRelativeTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value optionsInput)
-    : Object(state, proto)
-{
-#if defined(ENABLE_RUNTIME_ICU_BINDER)
-    UVersionInfo versionArray;
-    u_getVersion(versionArray);
-    if (versionArray[0] < 62) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Intl.NumberFormat needs 62+ version of ICU");
-    }
-#endif
-    // Let requestedLocales be ? CanonicalizeLocaleList(locales).
-    ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
-
-    Optional<Object*> options;
-    // If options is undefined, then
-    if (optionsInput.isUndefined()) {
-        // Let options be ObjectCreate(null).
-    } else {
-        // Else,
-        // Let options be ? ToObject(options).
-        options = optionsInput.toObject(state);
-    }
-
-    // Let opt be a new Record.
-    StringMap opt;
-    // Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
-    // Set opt.[[localeMatcher]] to matcher.
-    Value localeMatcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
-    String* matcher = localeMatcherValues[1].asString();
-    if (options) {
-        matcher = Intl::getOption(state, options.value(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, localeMatcherValues, 2, localeMatcherValues[1]).asString();
-    }
-    opt.insert(std::make_pair("matcher", matcher));
-
-    // Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
-    Value numberingSystem;
-    if (options) {
-        numberingSystem = Intl::getOption(state, options.value(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
-    }
-    // If numberingSystem is not undefined, then
-    if (!numberingSystem.isUndefined()) {
-        // If numberingSystem does not match the type sequence (from UTS 35 Unicode Locale Identifier, section 3.2), throw a RangeError exception.
-        if (!Intl::isValidUnicodeLocaleIdentifierTypeNonterminalOrTypeSequence(numberingSystem.asString())) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The numberingSystem value you gave is not valid");
-        }
-    }
-
-    // Set opt.[[nu]] to numberingSystem.
-    if (!numberingSystem.isUndefined()) {
-        opt.insert(std::make_pair("nu", numberingSystem.asString()));
-    }
-    // Let localeData be %RelativeTimeFormat%.[[LocaleData]].
-    // Let r be ResolveLocale(%RelativeTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %RelativeTimeFormat%.[[RelevantExtensionKeys]], localeData).
-    StringMap r = Intl::resolveLocale(state, state.context()->vmInstance()->intlRelativeTimeFormatAvailableLocales(), requestedLocales, opt, intlRelativeTimeFormatRelevantExtensionKeys, intlRelativeTimeFormatRelevantExtensionKeysLength, localeDataRelativeTimeFormat);
-    // Let locale be r.[[Locale]].
-    String* locale = r.at("locale");
-    // Set relativeTimeFormat.[[Locale]] to locale.
-    m_locale = locale;
-    // Set relativeTimeFormat.[[DataLocale]] to r.[[DataLocale]].
-    m_dataLocale = r.at("dataLocale");
-    // Set relativeTimeFormat.[[NumberingSystem]] to r.[[nu]].
-    m_numberingSystem = r.at("nu");
-    // Let s be ? GetOption(options, "style", "string", «"long", "short", "narrow"», "long").
-
-    Value styleValues[3] = { state.context()->staticStrings().lazyLong().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyNarrow().string() };
-    String* style = styleValues[0].asString();
-    // Set relativeTimeFormat.[[Style]] to s.
-    if (options) {
-        style = Intl::getOption(state, options.value(), state.context()->staticStrings().lazyStyle().string(), Intl::StringValue, styleValues, 3, styleValues[0]).asString();
-    }
-    m_style = style;
-    // Let numeric be ? GetOption(options, "numeric", "string", «"always", "auto"», "always").
-    Value numericValues[2] = { state.context()->staticStrings().lazyAlways().string(), state.context()->staticStrings().lazyAuto().string() };
-    String* numeric = numericValues[0].asString();
-    if (options) {
-        numeric = Intl::getOption(state, options.value(), state.context()->staticStrings().numeric.string(), Intl::StringValue, numericValues, 2, numericValues[0]).asString();
-    }
-    // Set relativeTimeFormat.[[Numeric]] to numeric.
-    m_numeric = numeric;
-    // Let relativeTimeFormat.[[NumberFormat]] be ! Construct(%NumberFormat%, « locale »).
-    // Let relativeTimeFormat.[[PluralRules]] be ! Construct(%PluralRules%, « locale »).
-    // Return relativeTimeFormat.
-
-    UDateRelativeDateTimeFormatterStyle icuStyle;
-    if (m_style->equals("short")) {
-        icuStyle = UDAT_STYLE_SHORT;
-    } else if (m_style->equals("narrow")) {
-        icuStyle = UDAT_STYLE_NARROW;
-    } else {
-        ASSERT(m_style->equals("long"));
-        icuStyle = UDAT_STYLE_LONG;
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    m_icuRelativeDateTimeFormatter = ureldatefmt_open(m_locale->toNonGCUTF8StringData().data(), nullptr, icuStyle, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, &status);
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize RelativeTimeFormat");
-    }
-
-    addFinalizer([](Object* obj, void* data) {
-        IntlRelativeTimeFormatObject* self = (IntlRelativeTimeFormatObject*)obj;
-        ureldatefmt_close(self->m_icuRelativeDateTimeFormatter);
-    },
-                 nullptr);
-}
-
-static URelativeDateTimeUnit icuRelativeTimeUnitFromString(String* unit)
-{
-    if (unit->equals("seconds") || unit->equals("second")) {
-        return UDAT_REL_UNIT_SECOND;
-    } else if (unit->equals("minutes") || unit->equals("minute")) {
-        return UDAT_REL_UNIT_MINUTE;
-    } else if (unit->equals("hours") || unit->equals("hour")) {
-        return UDAT_REL_UNIT_HOUR;
-    } else if (unit->equals("days") || unit->equals("day")) {
-        return UDAT_REL_UNIT_DAY;
-    } else if (unit->equals("weeks") || unit->equals("week")) {
-        return UDAT_REL_UNIT_WEEK;
-    } else if (unit->equals("months") || unit->equals("month")) {
-        return UDAT_REL_UNIT_MONTH;
-    } else if (unit->equals("quarters") || unit->equals("quarter")) {
-        return UDAT_REL_UNIT_QUARTER;
-    } else if (unit->equals("years") || unit->equals("year")) {
-        return UDAT_REL_UNIT_YEAR;
-    } else {
-        return UDAT_REL_UNIT_COUNT;
-    }
-}
-
-String* IntlRelativeTimeFormatObject::format(ExecutionState& state, double value, String* unit)
-{
-    // https://tc39.es/ecma402/#sec-PartitionRelativeTimePattern
-    if (std::isinf(value) || std::isnan(value) || !IS_IN_TIME_RANGE(value)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "value is valid in RelativeTimeFormat format()");
-    }
-
-    // https://tc39.es/ecma402/#sec-singularrelativetimeunit
-    URelativeDateTimeUnit icuUnit = icuRelativeTimeUnitFromString(unit);
-
-    if (icuUnit == UDAT_REL_UNIT_COUNT) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is invalid in RelativeTimeFormat format()");
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    int32_t bufSize;
-    if (m_numeric->equals("always")) {
-        bufSize = ureldatefmt_formatNumeric(m_icuRelativeDateTimeFormatter, value, icuUnit, nullptr, 0, &status);
-    } else {
-        bufSize = ureldatefmt_format(m_icuRelativeDateTimeFormatter, value, icuUnit, nullptr, 0, &status);
-    }
-
-    if (status != U_BUFFER_OVERFLOW_ERROR) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    status = U_ZERO_ERROR;
-    UChar* buf = (UChar*)alloca(sizeof(UChar) * (bufSize + 1));
-    if (m_numeric->equals("always")) {
-        ureldatefmt_formatNumeric(m_icuRelativeDateTimeFormatter, value, icuUnit, buf, bufSize + 1, &status);
-    } else {
-        ureldatefmt_format(m_icuRelativeDateTimeFormatter, value, icuUnit, buf, bufSize + 1, &status);
-    }
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-    return new UTF16String(buf, bufSize);
-}
-
-ArrayObject* IntlRelativeTimeFormatObject::formatToParts(ExecutionState& state, double value, String* unit)
-{
-    // https://tc39.es/ecma402/#sec-PartitionRelativeTimePattern
-    if (std::isinf(value) || std::isnan(value) || !IS_IN_TIME_RANGE(value)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "value is valid in RelativeTimeFormat formatToParts()");
-    }
-
-    // https://tc39.es/ecma402/#sec-singularrelativetimeunit
-    URelativeDateTimeUnit icuUnit = icuRelativeTimeUnitFromString(unit);
-
-    if (icuUnit == UDAT_REL_UNIT_COUNT) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "unit is invalid in RelativeTimeFormat formatToParts()");
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    LocalResourcePointer<UFormattedRelativeDateTime> formattedRelativeDateTime(ureldatefmt_openResult(&status), [](UFormattedRelativeDateTime* f) { ureldatefmt_closeResult(f); });
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    if (m_numeric->equals("always")) {
-        ureldatefmt_formatNumericToResult(m_icuRelativeDateTimeFormatter, value, icuUnit, formattedRelativeDateTime.get(), &status);
-    } else {
-        ureldatefmt_formatToResult(m_icuRelativeDateTimeFormatter, value, icuUnit, formattedRelativeDateTime.get(), &status);
-    }
-
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    const UFormattedValue* formattedValue = ureldatefmt_resultAsValue(formattedRelativeDateTime.get(), &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    int32_t strLength;
-    const char16_t* str = ufmtval_getString(formattedValue, &strLength, &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    UTF16StringDataNonGCStd resultString(str, strLength);
-
-    LocalResourcePointer<UConstrainedFieldPosition> fpos(ucfpos_open(&status), [](UConstrainedFieldPosition* f) { ucfpos_close(f); });
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    ucfpos_constrainCategory(fpos.get(), UFIELD_CATEGORY_NUMBER, &status);
-    if (U_FAILURE(status)) {
-        ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-    }
-
-    std::vector<Intl::NumberFieldItem> fields;
-
-    while (true) {
-        bool hasNext = ufmtval_nextPosition(formattedValue, fpos.get(), &status);
-        if (U_FAILURE(status)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-        }
-        if (!hasNext) {
-            break;
-        }
-
-        int32_t type = ucfpos_getField(fpos.get(), &status);
-        if (U_FAILURE(status)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-        }
-
-        int32_t start, end;
-        ucfpos_getIndexes(fpos.get(), &start, &end, &status);
-        if (U_FAILURE(status)) {
-            ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to format time");
-        }
-
-        Intl::NumberFieldItem item;
-        item.start = start;
-        item.end = end;
-        item.type = type;
-
-        fields.push_back(item);
-    }
-
-    Intl::convertICUNumberFieldToEcmaNumberField(fields, value, resultString);
-
-    if (icuUnit == UDAT_REL_UNIT_SECOND) {
-        unit = state.context()->staticStrings().lazySecond().string();
-    } else if (icuUnit == UDAT_REL_UNIT_MINUTE) {
-        unit = state.context()->staticStrings().lazyMinute().string();
-    } else if (icuUnit == UDAT_REL_UNIT_HOUR) {
-        unit = state.context()->staticStrings().lazyHour().string();
-    } else if (icuUnit == UDAT_REL_UNIT_DAY) {
-        unit = state.context()->staticStrings().lazyDay().string();
-    } else if (icuUnit == UDAT_REL_UNIT_WEEK) {
-        unit = state.context()->staticStrings().lazyWeek().string();
-    } else if (icuUnit == UDAT_REL_UNIT_MONTH) {
-        unit = state.context()->staticStrings().lazyMonth().string();
-    } else if (icuUnit == UDAT_REL_UNIT_QUARTER) {
-        unit = state.context()->staticStrings().lazyQuarter().string();
-    } else {
-        ASSERT(icuUnit == UDAT_REL_UNIT_YEAR);
-        unit = state.context()->staticStrings().lazyYear().string();
-    }
-
-    AtomicString unitAtom(state, "unit");
-    AtomicString typeAtom(state, "type");
-    AtomicString valueAtom = state.context()->staticStrings().value;
-
-    ArrayObject* result = new ArrayObject(state);
-    for (size_t i = 0; i < fields.size(); i++) {
-        const Intl::NumberFieldItem& item = fields[i];
-
-        Object* o = new Object(state);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(typeAtom), ObjectPropertyDescriptor(Intl::icuNumberFieldToString(state, item.type, value), ObjectPropertyDescriptor::AllPresent));
-        auto sub = resultString.substr(item.start, item.end - item.start);
-        o->defineOwnPropertyThrowsException(state, ObjectPropertyName(valueAtom), ObjectPropertyDescriptor(new UTF16String(sub.data(), sub.length()), ObjectPropertyDescriptor::AllPresent));
-        if (item.type != -1) {
-            o->defineOwnPropertyThrowsException(state, ObjectPropertyName(unitAtom), ObjectPropertyDescriptor(unit, ObjectPropertyDescriptor::AllPresent));
-        }
-
-        result->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, i), ObjectPropertyDescriptor(o, ObjectPropertyDescriptor::AllPresent));
-    }
-
-    return result;
-}
-
-} // namespace Escargot
-#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/IntlRelativeTimeFormat.h
deleted file mode 100644 (file)
index 91dc6ec..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
- *  USA
- */
-
-
-#ifndef __EscargotIntlRelativeTimeFormat__
-#define __EscargotIntlRelativeTimeFormat__
-
-#include "runtime/Object.h"
-
-namespace Escargot {
-
-class IntlRelativeTimeFormatObject : public Object {
-public:
-    IntlRelativeTimeFormatObject(ExecutionState& state, Value locales, Value options);
-    IntlRelativeTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value options);
-
-    virtual bool isIntlRelativeTimeFormatObject() const override
-    {
-        return true;
-    }
-
-    String* locale() const
-    {
-        return m_locale;
-    }
-
-    String* dataLocale() const
-    {
-        return m_dataLocale;
-    }
-
-    String* numberingSystem() const
-    {
-        return m_numberingSystem;
-    }
-
-    String* style() const
-    {
-        return m_style;
-    }
-
-    String* numeric() const
-    {
-        return m_numeric;
-    }
-
-    String* format(ExecutionState& state, double value, String* unit);
-    ArrayObject* formatToParts(ExecutionState& state, double value, String* unit);
-
-protected:
-    String* m_locale;
-    String* m_dataLocale;
-    String* m_numberingSystem;
-    String* m_style;
-    String* m_numeric;
-
-    URelativeDateTimeFormatter* m_icuRelativeDateTimeFormatter;
-};
-
-} // namespace Escargot
-#endif
-#endif
index da6825b2aeeab455b6f7fb6e3ce980b3d8e85913..4f81a1a15d6f1e505e4ccdf57ee3780aed35962f 100644 (file)
@@ -87,6 +87,7 @@ ObjectRareData::ObjectRareData(Object* obj)
     , m_isArrayObjectLengthWritable(true)
     , m_isSpreadArrayObject(false)
     , m_isFinalizerRegistered(false)
+    , m_isInlineCacheable(true)
     , m_shouldUpdateEnumerateObject(false)
     , m_hasNonWritableLastIndexRegExpObject(false)
     , m_hasExtendedExtraData(false)
@@ -1460,6 +1461,11 @@ void Object::deleteOwnProperty(ExecutionState& state, size_t idx)
     // ASSERT(m_values.size() == m_structure->propertyCount());
 }
 
+void Object::markAsNonInlineCachable()
+{
+    ensureRareData()->m_isInlineCacheable = false;
+}
+
 uint64_t Object::length(ExecutionState& state)
 {
     // ToLength(Get(obj, "length"))
@@ -1641,6 +1647,10 @@ bool Object::defineNativeDataAccessorProperty(ExecutionState& state, const Objec
     m_structure = m_structure->addProperty(P.toObjectStructurePropertyName(state), ObjectStructurePropertyDescriptor::createDataButHasNativeGetterSetterDescriptor(data));
     m_values.pushBack(objectInternalData, m_structure->propertyCount());
 
+    if (UNLIKELY(data->m_actsLikeJSGetterSetter)) {
+        markAsNonInlineCachable();
+    }
+
     return true;
 }
 
index 7a08cccea9118772531635c7fcfc1006280d8168..f1bcf7c2e68dfefc33d3eae17d7effc809efc7b1 100644 (file)
@@ -74,6 +74,7 @@ struct ObjectRareData : public PointerValue {
     bool m_isArrayObjectLengthWritable : 1;
     bool m_isSpreadArrayObject : 1;
     bool m_isFinalizerRegistered : 1;
+    bool m_isInlineCacheable : 1;
     bool m_shouldUpdateEnumerateObject : 1; // used only for Array Object when ArrayObject::deleteOwnProperty called
     bool m_hasNonWritableLastIndexRegExpObject : 1;
     bool m_hasExtendedExtraData : 1;
@@ -767,6 +768,7 @@ class Object : public PointerValue {
     friend class EnumerateObjectWithDestruction;
     friend class EnumerateObjectWithIteration;
     friend struct ObjectRareData;
+    friend class Template;
     friend class ObjectTemplate;
 
 public:
@@ -955,6 +957,9 @@ public:
 
     virtual bool isInlineCacheable()
     {
+        if (UNLIKELY(hasRareData())) {
+            return rareData()->m_isInlineCacheable;
+        }
         return true;
     }
 
@@ -1239,6 +1244,8 @@ protected:
     void setGlobalIntrinsicObject(ExecutionState& state, bool isPrototype = false);
 
     void deleteOwnProperty(ExecutionState& state, size_t idx);
+
+    void markAsNonInlineCachable();
 };
 } // namespace Escargot
 
index 60c2b0e224281d2889192f9bbede0aa00bc05505..fca2091eed4c7920c44f82fda2a3ce15ce7f664c 100644 (file)
@@ -261,7 +261,7 @@ private:
 
 Object* ObjectTemplate::instantiate(Context* ctx)
 {
-    if (!m_cachedObjectStructure) {
+    if (!m_cachedObjectStructure.m_objectStructure) {
         m_cachedObjectStructure = constructObjectStructure(ctx, nullptr, 0);
     }
     ObjectPropertyValueVector objectPropertyValues;
@@ -278,9 +278,9 @@ Object* ObjectTemplate::instantiate(Context* ctx)
     }
 
     if (m_namedPropertyHandler) {
-        result = new ObjectWithNamedPropertyHandler(m_cachedObjectStructure, std::move(objectPropertyValues), proto, m_namedPropertyHandler);
+        result = new ObjectWithNamedPropertyHandler(m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), proto, m_namedPropertyHandler);
     } else {
-        result = new Object(m_cachedObjectStructure, std::move(objectPropertyValues), proto);
+        result = new Object(m_cachedObjectStructure.m_objectStructure, std::move(objectPropertyValues), proto);
     }
 
     postProcessing(result);
@@ -335,6 +335,9 @@ bool ObjectTemplate::installTo(Context* ctx, Object* target)
             } else if (type == Template::TemplatePropertyData::PropertyType::PropertyNativeAccessorData) {
                 sender->target->defineNativeDataAccessorProperty(state, name, properties[i].second.nativeAccessorData(),
                                                                  Value(Value::FromPayload, (intptr_t)properties[i].second.nativeAccessorPrivateData()));
+                if (properties[i].second.nativeAccessorData()->m_actsLikeJSGetterSetter) {
+                    sender->target->markAsNonInlineCachable();
+                }
             } else {
                 ASSERT(type == Template::TemplatePropertyData::PropertyType::PropertyAccessorData);
                 Value getter = properties[i].second.accessorData().m_getterTemplate ? properties[i].second.accessorData().m_getterTemplate->instantiate(sender->ctx) : Value(Value::EmptyValue);
index 2bd2d404565e5fd368817f916371135728cba50a..5c2888eccd3a30b0b7e3adfca79d23364b47c14b 100644 (file)
 #ifndef __EscargotPlatform__
 #define __EscargotPlatform__
 
-#include "runtime/SandBox.h"
-
 namespace Escargot {
 
-class ArrayBufferObject;
-class PromiseObject;
 class Context;
-class Job;
+class Script;
+class String;
+class PromiseObject;
 
-class Platform : public gc {
+class Platform {
 public:
     virtual ~Platform() {}
     // ArrayBuffer
@@ -49,6 +47,10 @@ public:
     virtual LoadModuleResult onLoadModule(Context* relatedContext, Script* whereRequestFrom, String* moduleSrc) = 0;
     virtual void didLoadModule(Context* relatedContext, Optional<Script*> whereRequestFrom, Script* loadedModule) = 0;
     virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) = 0;
+
+    // ThreadLocal custom data (g_customData)
+    virtual void* allocateThreadLocalCustomData() = 0;
+    virtual void deallocateThreadLocalCustomData() = 0;
 };
 } // namespace Escargot
 
index 8b1c271f0a43f6e2a44f284bbf97170cb391473a..dc0c61fa4cbb2226b4bf52568b93d2467db8424d 100644 (file)
@@ -52,6 +52,7 @@ class GlobalObject;
 class BoundFunctionObject;
 class PromiseObject;
 class ProxyObject;
+class ArrayBuffer;
 class ArrayBufferObject;
 class ArrayBufferView;
 class DoubleInEncodedValue;
@@ -70,9 +71,7 @@ class AsyncFromSyncIteratorObject;
 class GlobalObjectProxyObject;
 class TypedArrayObject;
 class ModuleNamespaceObject;
-#if defined(ENABLE_THREADING)
 class SharedArrayBufferObject;
-#endif
 #if defined(ENABLE_INTL)
 class IntlLocaleObject;
 class IntlPluralRulesObject;
@@ -107,7 +106,7 @@ class ExportedFunctionObject;
 class PointerValue : public gc {
     friend class Object;
     friend class Context;
-    friend class VMInstance;
+    friend class Global;
     friend class ByteCodeInterpreter;
 
     // tag values for fast type check
@@ -291,6 +290,11 @@ public:
         return false;
     }
 
+    virtual bool isArrayBuffer() const
+    {
+        return false;
+    }
+
     virtual bool isArrayBufferObject() const
     {
         return false;
@@ -411,12 +415,10 @@ public:
         return false;
     }
 
-#if defined(ENABLE_THREADING)
     virtual bool isSharedArrayBufferObject() const
     {
         return false;
     }
-#endif
 
 #if defined(ENABLE_INTL)
     virtual bool isIntlLocaleObject() const
@@ -652,6 +654,12 @@ public:
         return (ProxyObject*)this;
     }
 
+    ArrayBuffer* asArrayBuffer()
+    {
+        ASSERT(isArrayBuffer());
+        return (ArrayBuffer*)this;
+    }
+
     ArrayBufferObject* asArrayBufferObject()
     {
         ASSERT(isArrayBufferObject());
@@ -760,6 +768,11 @@ public:
         ASSERT(isSharedArrayBufferObject());
         return (SharedArrayBufferObject*)this;
     }
+#else
+    SharedArrayBufferObject* asSharedArrayBufferObject()
+    {
+        RELEASE_ASSERT_NOT_REACHED();
+    }
 #endif
 
 #if defined(ENABLE_INTL)
index 1328530166f5648d73b449d39abb6a380cf3e8b2..dd61b56618f9c7289ba441d64da7c171baa83e8a 100644 (file)
  */
 
 #include "Escargot.h"
+#include "ThreadLocal.h"
 #include "RegExpObject.h"
 #include "Context.h"
 #include "ArrayObject.h"
-#include "VMInstance.h"
 
 #include "WTFBridge.h"
 #include "Yarr.h"
@@ -307,7 +307,7 @@ bool RegExpObject::match(ExecutionState& state, String* str, RegexMatchResult& m
         if (entry.m_bytecodePattern) {
             m_bytecodePattern = entry.m_bytecodePattern;
         } else {
-            WTF::BumpPointerAllocator* bumpAlloc = VMInstance::bumpPointerAllocator();
+            WTF::BumpPointerAllocator* bumpAlloc = ThreadLocal::bumpPointerAllocator();
             std::unique_ptr<JSC::Yarr::BytecodePattern> ownedBytecode = JSC::Yarr::byteCompile(*m_yarrPattern, bumpAlloc);
             m_bytecodePattern = ownedBytecode.release();
             entry.m_bytecodePattern = m_bytecodePattern;
index 1812a76db51c4f0938855938b89a498576aae8c7..11f3dfd911d6dfdcff177e9bced2341191612933 100644 (file)
 #if defined(ENABLE_THREADING)
 
 #include "Escargot.h"
-#include "runtime/VMInstance.h"
 #include "runtime/Context.h"
-#include "runtime/BackingStore.h"
-#include "runtime/ArrayBufferObject.h"
+#include "runtime/Global.h"
+#include "runtime/Platform.h"
 #include "runtime/SharedArrayBufferObject.h"
 
 namespace Escargot {
 
+static void backingStoreDeleter(void* data, size_t length, void* deleterData)
+{
+    SharedArrayBufferObjectBackingStoreData* internalData = (SharedArrayBufferObjectBackingStoreData*)deleterData;
+    internalData->deref();
+}
+
+void SharedArrayBufferObjectBackingStoreData::deref()
+{
+    auto oldValue = m_refCount.fetch_sub(1);
+    if (oldValue == 1) {
+        Global::platform()->onFreeArrayBufferObjectDataBuffer(m_data, m_byteLength);
+        delete this;
+    }
+}
+
 SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength)
-    : ArrayBufferObject(state, proto)
+    : ArrayBuffer(state, proto)
 {
-    ASSERT(byteLength < ArrayBufferObject::maxArrayBufferSize);
+    ASSERT(byteLength < ArrayBuffer::maxArrayBufferSize);
 
     m_mayPointsSharedBackingStore = true;
 
@@ -46,13 +60,18 @@ SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object*
         GC_invoke_finalizers();
     }
 
-    auto platform = state.context()->vmInstance()->platform();
-    void* buffer = platform->onMallocArrayBufferObjectDataBuffer(byteLength);
-    m_backingStore = new BackingStore(buffer, byteLength, [](void* data, size_t length, void* deleterData) {
-        Platform* platform = (Platform*)deleterData;
-        platform->onFreeArrayBufferObjectDataBuffer(data, length);
-    },
-                                      platform, true);
+    void* buffer = Global::platform()->onMallocArrayBufferObjectDataBuffer(byteLength);
+    SharedArrayBufferObjectBackingStoreData* internalData = new SharedArrayBufferObjectBackingStoreData(buffer, byteLength);
+
+    m_backingStore = new BackingStore(buffer, byteLength, backingStoreDeleter, internalData, true);
+}
+
+SharedArrayBufferObject::SharedArrayBufferObject(ExecutionState& state, Object* proto, SharedArrayBufferObjectBackingStoreData* data)
+    : ArrayBuffer(state, proto)
+{
+    data->ref();
+    m_mayPointsSharedBackingStore = true;
+    m_backingStore = new BackingStore(data->data(), data->byteLength(), backingStoreDeleter, data, true);
 }
 
 SharedArrayBufferObject* SharedArrayBufferObject::allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength)
@@ -62,7 +81,7 @@ SharedArrayBufferObject* SharedArrayBufferObject::allocateSharedArrayBuffer(Exec
         return constructorRealm->globalObject()->sharedArrayBufferPrototype();
     });
 
-    if (byteLength >= ArrayBufferObject::maxArrayBufferSize) {
+    if (byteLength >= ArrayBuffer::maxArrayBufferSize) {
         ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, state.context()->staticStrings().SharedArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize);
     }
 
@@ -77,8 +96,7 @@ void* SharedArrayBufferObject::operator new(size_t size)
     static MAY_THREAD_LOCAL GC_descr descr;
     if (!typeInited) {
         GC_word obj_bitmap[GC_BITMAP_SIZE(SharedArrayBufferObject)] = { 0 };
-        Object::fillGCDescriptor(obj_bitmap);
-        GC_set_bit(obj_bitmap, GC_WORD_OFFSET(SharedArrayBufferObject, m_backingStore));
+        ArrayBuffer::fillGCDescriptor(obj_bitmap);
         descr = GC_make_descriptor(obj_bitmap, GC_WORD_LEN(SharedArrayBufferObject));
         typeInited = true;
     }
index a45f1db2c39e6390aa0937e7c3966a8751f27efa..d2f740468b89606261b029c79f3d796da8c67735 100644 (file)
 #ifndef __EscargotSharedArrayBufferObject__
 #define __EscargotSharedArrayBufferObject__
 
-namespace Escargot {
+#include "runtime/ArrayBuffer.h"
 
-class BackingStore;
-class ArrayBufferObject;
+namespace Escargot {
 
-class SharedArrayBufferObject : public ArrayBufferObject {
+class SharedArrayBufferObjectBackingStoreData {
 public:
-    SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength);
+    SharedArrayBufferObjectBackingStoreData(void* data, size_t byteLength)
+        : m_data(data)
+        , m_byteLength(byteLength)
+        , m_refCount(1)
+    {
+    }
 
-    static SharedArrayBufferObject* allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength);
+    void* data() const
+    {
+        return m_data;
+    }
 
-    Optional<BackingStore*> backingStore()
+    size_t byteLength() const
     {
-        return m_backingStore;
+        return m_byteLength;
     }
 
-    virtual bool isSharedArrayBufferObject() const
+    void ref()
+    {
+        m_refCount++;
+    }
+
+    void deref();
+
+private:
+    void* m_data;
+    size_t m_byteLength;
+    std::atomic<size_t> m_refCount;
+};
+
+class SharedArrayBufferObject : public ArrayBuffer {
+public:
+    SharedArrayBufferObject(ExecutionState& state, Object* proto, size_t byteLength);
+    SharedArrayBufferObject(ExecutionState& state, Object* proto, SharedArrayBufferObjectBackingStoreData* data);
+
+    static SharedArrayBufferObject* allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength);
+
+    virtual bool isSharedArrayBufferObject() const override
     {
         return true;
     }
index b7766bd6d00506f8fcd8bd586a6717ce8ec41820..f1d6321f305d133834ab71281fb9bf4cf6d9e78b 100644 (file)
@@ -44,7 +44,7 @@ bool Template::has(const TemplatePropertyName& name)
 
 bool Template::remove(const TemplatePropertyName& name)
 {
-    ASSERT(m_cachedObjectStructure == nullptr);
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
     for (size_t i = 0; i < m_properties.size(); i++) {
         if (m_properties[i].first == name) {
             m_properties.erase(i);
@@ -56,26 +56,26 @@ bool Template::remove(const TemplatePropertyName& name)
 
 void Template::set(const TemplatePropertyName& name, const TemplateData& data, bool isWritable, bool isEnumerable, bool isConfigurable)
 {
-    ASSERT(m_cachedObjectStructure == nullptr);
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
     remove(name);
     m_properties.pushBack(std::make_pair(name, TemplatePropertyData(data, isWritable, isEnumerable, isConfigurable)));
 }
 
 void Template::setAccessorProperty(const TemplatePropertyName& name, Optional<FunctionTemplate*> getter, Optional<FunctionTemplate*> setter, bool isEnumerable, bool isConfigurable)
 {
-    ASSERT(m_cachedObjectStructure == nullptr);
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
     remove(name);
     m_properties.pushBack(std::make_pair(name, TemplatePropertyData(getter, setter, isEnumerable, isConfigurable)));
 }
 
 void Template::setNativeDataAccessorProperty(const TemplatePropertyName& name, ObjectPropertyNativeGetterSetterData* nativeGetterSetterData, void* privateData)
 {
-    ASSERT(m_cachedObjectStructure == nullptr);
+    ASSERT(m_cachedObjectStructure.m_objectStructure == nullptr);
     remove(name);
     m_properties.pushBack(std::make_pair(name, TemplatePropertyData(nativeGetterSetterData, privateData)));
 }
 
-ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount)
+Template::CachedObjectStructure Template::constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount)
 {
     size_t propertyCount = m_properties.size() + baseItemCount;
     ObjectStructureItemTightVector structureItemVector;
@@ -87,6 +87,7 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur
 
     bool hasIndexStringAsPropertyName = false;
     bool hasNonAtomicPropertyName = false;
+    bool isInlineNonCacheable = false;
     for (size_t i = baseItemCount; i < propertyCount; i++) {
         auto propertyIndex = i - baseItemCount;
         auto propertyName = m_properties[propertyIndex].first.toObjectStructurePropertyName(ctx);
@@ -102,6 +103,7 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur
             desc = ObjectStructurePropertyDescriptor::createDataDescriptor(m_properties[propertyIndex].second.presentAttributes());
         } else if (type == Template::TemplatePropertyData::PropertyType::PropertyNativeAccessorData) {
             desc = ObjectStructurePropertyDescriptor::createDataButHasNativeGetterSetterDescriptor(m_properties[propertyIndex].second.nativeAccessorData());
+            isInlineNonCacheable = isInlineNonCacheable | m_properties[propertyIndex].second.nativeAccessorData()->m_actsLikeJSGetterSetter;
         } else {
             ASSERT(type == Template::TemplatePropertyData::PropertyType::PropertyAccessorData);
             desc = ObjectStructurePropertyDescriptor::createAccessorDescriptor(m_properties[propertyIndex].second.presentAttributes());
@@ -116,7 +118,10 @@ ObjectStructure* Template::constructObjectStructure(Context* ctx, ObjectStructur
         newObjectStructure = new ObjectStructureWithTransition(std::move(structureItemVector), hasIndexStringAsPropertyName, hasNonAtomicPropertyName);
     }
 
-    return newObjectStructure;
+    CachedObjectStructure s;
+    s.m_objectStructure = newObjectStructure;
+    s.m_inlineCacheable = !isInlineNonCacheable;
+    return s;
 }
 
 void Template::constructObjectPropertyValues(Context* ctx, ObjectPropertyValue* baseItems, size_t baseItemCount, ObjectPropertyValueVector& objectPropertyValues)
@@ -151,5 +156,9 @@ void Template::postProcessing(Object* instantiatedObject)
     if (m_instanceExtraData) {
         instantiatedObject->setExtraData(m_instanceExtraData);
     }
+
+    if (!m_cachedObjectStructure.m_inlineCacheable) {
+        instantiatedObject->markAsNonInlineCachable();
+    }
 }
 } // namespace Escargot
index bdfd3c06afa4da59dfe56683e031cc226bf73ba0..7761bb80732b0c5505a3e17e2bb0b842f5956990 100644 (file)
@@ -158,7 +158,7 @@ public:
     virtual Object* instantiate(Context* ctx) = 0;
     bool didInstantiate() const
     {
-        return m_cachedObjectStructure;
+        return m_cachedObjectStructure.m_objectStructure;
     }
 
     virtual bool isObjectTemplate() const
@@ -173,17 +173,26 @@ public:
 
     Optional<ObjectStructure*> cachedObjectStructure()
     {
-        return m_cachedObjectStructure;
+        return m_cachedObjectStructure.m_objectStructure;
     }
 
 protected:
-    ObjectStructure* constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount);
+    struct CachedObjectStructure {
+        ObjectStructure* m_objectStructure;
+        bool m_inlineCacheable;
+
+        CachedObjectStructure()
+            : m_objectStructure(nullptr)
+            , m_inlineCacheable(false)
+        {
+        }
+    };
+    CachedObjectStructure constructObjectStructure(Context* ctx, ObjectStructureItem* baseItems, size_t baseItemCount);
     void constructObjectPropertyValues(Context* ctx, ObjectPropertyValue* baseItems, size_t baseItemCount, ObjectPropertyValueVector& objectPropertyValues);
     void postProcessing(Object* instantiatedObject);
 
     Template()
         : m_instanceExtraData(nullptr)
-        , m_cachedObjectStructure(nullptr)
     {
     }
     virtual ~Template()
@@ -194,7 +203,7 @@ protected:
     {
         GC_set_bit(desc, GC_WORD_OFFSET(Template, m_properties));
         GC_set_bit(desc, GC_WORD_OFFSET(Template, m_instanceExtraData));
-        GC_set_bit(desc, GC_WORD_OFFSET(Template, m_cachedObjectStructure));
+        GC_set_bit(desc, GC_WORD_OFFSET(Template, m_cachedObjectStructure.m_objectStructure));
     }
 
     class TemplatePropertyData {
@@ -332,7 +341,7 @@ protected:
 
     Vector<std::pair<TemplatePropertyName, TemplatePropertyData>, GCUtil::gc_malloc_allocator<std::pair<TemplatePropertyName, TemplatePropertyData>>> m_properties;
     void* m_instanceExtraData;
-    ObjectStructure* m_cachedObjectStructure;
+    CachedObjectStructure m_cachedObjectStructure;
 };
 } // namespace Escargot
 
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.cpp
new file mode 100644 (file)
index 0000000..07e3547
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "runtime/ThreadLocal.h"
+#include "heap/Heap.h"
+#include "runtime/Global.h"
+#include "runtime/Platform.h"
+#include "parser/ASTAllocator.h"
+#include "BumpPointerAllocator.h"
+#if defined(ENABLE_WASM)
+#include "wasm.h"
+#endif
+
+namespace Escargot {
+
+MAY_THREAD_LOCAL bool ThreadLocal::inited;
+
+MAY_THREAD_LOCAL std::mt19937* ThreadLocal::g_randEngine;
+MAY_THREAD_LOCAL bf_context_t ThreadLocal::g_bfContext;
+#if defined(ENABLE_WASM)
+MAY_THREAD_LOCAL WASMContext ThreadLocal::g_wasmContext;
+#endif
+MAY_THREAD_LOCAL ASTAllocator* ThreadLocal::g_astAllocator;
+MAY_THREAD_LOCAL WTF::BumpPointerAllocator* ThreadLocal::g_bumpPointerAllocator;
+MAY_THREAD_LOCAL void* ThreadLocal::g_customData;
+
+void ThreadLocal::initialize()
+{
+    // initialize should be invoked only once in each thread
+    static MAY_THREAD_LOCAL bool called_once = true;
+    RELEASE_ASSERT(called_once && !inited);
+
+    // Heap is initialized for each thread
+    Heap::initialize();
+
+    // g_randEngine
+    g_randEngine = new std::mt19937((unsigned int)time(NULL));
+
+    // g_bfContext
+    bf_context_init(&g_bfContext, [](void* opaque, void* ptr, size_t size) -> void* {
+        return realloc(ptr, size);
+    },
+                    nullptr);
+
+#if defined(ENABLE_WASM)
+    // g_wasmContext
+    g_wasmContext.engine = wasm_engine_new();
+    g_wasmContext.store = wasm_store_new(g_wasmContext.engine);
+    g_wasmContext.lastGCCheckTime = 0;
+#endif
+
+    // g_astAllocator
+    g_astAllocator = new ASTAllocator();
+
+    // g_bumpPointerAllocator
+    g_bumpPointerAllocator = new WTF::BumpPointerAllocator();
+
+    // g_customData
+    g_customData = Global::platform()->allocateThreadLocalCustomData();
+
+    called_once = false;
+    inited = true;
+}
+
+void ThreadLocal::finalize()
+{
+    // finalize should be invoked only once in each thread
+    static MAY_THREAD_LOCAL bool called_once = true;
+    RELEASE_ASSERT(called_once && inited);
+
+    // g_customData
+    Global::platform()->deallocateThreadLocalCustomData();
+    g_customData = nullptr;
+
+    // full gc(Heap::finalize) should be invoked after g_customData deallocation
+    // because g_customData might contain GC-object
+    Heap::finalize();
+
+    // g_randEngine does not need finalization
+    delete g_randEngine;
+    g_randEngine = nullptr;
+
+    // g_bfContext
+    bf_context_end(&g_bfContext);
+
+#if defined(ENABLE_WASM)
+    // g_wasmContext
+    wasm_store_delete(g_wasmContext.store);
+    wasm_engine_delete(g_wasmContext.engine);
+    g_wasmContext.store = nullptr;
+    g_wasmContext.engine = nullptr;
+    g_wasmContext.lastGCCheckTime = 0;
+#endif
+
+    // g_astAllocator
+    delete g_astAllocator;
+    g_astAllocator = nullptr;
+
+    // g_bumpPointerAllocator
+    delete g_bumpPointerAllocator;
+    g_bumpPointerAllocator = nullptr;
+
+    called_once = false;
+    inited = false;
+}
+
+#if defined(ENABLE_WASM)
+void ThreadLocal::wasmGC(uint64_t lastCheckTime)
+{
+    ASSERT(inited && !!g_wasmContext.store);
+    wasm_store_gc(g_wasmContext.store);
+    g_wasmContext.lastGCCheckTime = lastCheckTime;
+}
+#endif
+
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/ThreadLocal.h
new file mode 100644 (file)
index 0000000..b313453
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotThreadLocalRecord__
+#define __EscargotThreadLocalRecord__
+
+namespace WTF {
+class BumpPointerAllocator;
+}
+
+#if defined(ENABLE_WASM)
+struct wasm_engine_t;
+struct wasm_store_t;
+struct WASMContext {
+    wasm_engine_t* engine;
+    wasm_store_t* store;
+    uint64_t lastGCCheckTime;
+};
+#endif
+
+namespace Escargot {
+
+class ASTAllocator;
+
+// ThreadLocal has thread-local values
+// ThreadLocal should be created for each thread
+// ThreadLocal is a non-GC global object which means that users who want to customize it should manage memory by themselves
+class ThreadLocal {
+    static MAY_THREAD_LOCAL bool inited;
+
+    // Global data per thread
+    static MAY_THREAD_LOCAL std::mt19937* g_randEngine;
+    static MAY_THREAD_LOCAL bf_context_t g_bfContext;
+#if defined(ENABLE_WASM)
+    static MAY_THREAD_LOCAL WASMContext g_wasmContext;
+#endif
+    static MAY_THREAD_LOCAL ASTAllocator* g_astAllocator;
+    static MAY_THREAD_LOCAL WTF::BumpPointerAllocator* g_bumpPointerAllocator;
+    // custom data allocated by user through Platform::allocateThreadLocalCustomData
+    static MAY_THREAD_LOCAL void* g_customData;
+
+public:
+    static void initialize();
+    static void finalize();
+
+    // Global data getter
+    static std::mt19937& randEngine()
+    {
+        ASSERT(inited && !!g_randEngine);
+        return *g_randEngine;
+    }
+
+    static bf_context_t* bfContext()
+    {
+        ASSERT(inited && !!g_bfContext.realloc_func);
+        return &g_bfContext;
+    }
+
+#if defined(ENABLE_WASM)
+    static void wasmGC(uint64_t lastCheckTime);
+
+    static wasm_store_t* wasmStore()
+    {
+        ASSERT(inited && !!g_wasmContext.store);
+        return g_wasmContext.store;
+    }
+
+    static uint64_t wasmLastGCCheckTime()
+    {
+        ASSERT(inited && !!g_wasmContext.store);
+        return g_wasmContext.lastGCCheckTime;
+    }
+#endif
+
+    static ASTAllocator* astAllocator()
+    {
+        ASSERT(inited && !!g_astAllocator);
+        return g_astAllocator;
+    }
+
+    static WTF::BumpPointerAllocator* bumpPointerAllocator()
+    {
+        ASSERT(inited && !!g_bumpPointerAllocator);
+        return g_bumpPointerAllocator;
+    }
+
+    static void* customData()
+    {
+        ASSERT(inited && !!g_customData);
+        return g_customData;
+    }
+};
+
+} // namespace Escargot
+
+#endif
index b3726bdc45ac52e351ce39b1c0bd4a4e9dc31c63..12195f8632dd73f522b484820312910b27c9f9cf 100644 (file)
@@ -146,7 +146,7 @@ void TypedArrayObject::sort(ExecutionState& state, int64_t length, const std::fu
     }
 }
 
-ArrayBufferObject* TypedArrayObject::validateTypedArray(ExecutionState& state, const Value& O)
+ArrayBuffer* TypedArrayObject::validateTypedArray(ExecutionState& state, const Value& O)
 {
     if (!O.isObject()) {
         ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_ThisNotObject);
@@ -158,7 +158,7 @@ ArrayBufferObject* TypedArrayObject::validateTypedArray(ExecutionState& state, c
     }
 
     auto wrapper = thisObject->asTypedArrayObject();
-    ArrayBufferObject* buffer = wrapper->buffer();
+    ArrayBuffer* buffer = wrapper->buffer();
     buffer->throwTypeErrorIfDetached(state);
     return buffer;
 }
index 008036ac54c33739b3946ba4efbf2d9f41a1b2c5..47dfa1fe64d266f76f211c7f4ab3c3ffb86e7906 100644 (file)
@@ -81,7 +81,7 @@ public:
     virtual void enumeration(ExecutionState& state, bool (*callback)(ExecutionState& state, Object* self, const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc, void* data), void* data, bool shouldSkipSymbolKey) override;
     virtual void sort(ExecutionState& state, int64_t length, const std::function<bool(const Value& a, const Value& b)>& comp) override;
 
-    static ArrayBufferObject* validateTypedArray(ExecutionState& state, const Value& O);
+    static ArrayBuffer* validateTypedArray(ExecutionState& state, const Value& O);
 
 protected:
     explicit TypedArrayObject(ExecutionState& state, Object* proto)
index 6fb6d0378103907d68aafe340f20216b1980facc..70492b5a9e0b805c5175a21ea5ba1f8022054dd4 100644 (file)
@@ -19,7 +19,9 @@
 
 #include "Escargot.h"
 #include "VMInstance.h"
-#include "BumpPointerAllocator.h"
+#include "runtime/Global.h"
+#include "runtime/ThreadLocal.h"
+#include "runtime/Platform.h"
 #include "runtime/ArrayObject.h"
 #include "runtime/ArrayBufferObject.h"
 #include "runtime/StringObject.h"
 #include "runtime/JobQueue.h"
 #include "runtime/CompressibleString.h"
 #include "runtime/ReloadableString.h"
-#include "runtime/Intl.h"
+#include "intl/Intl.h"
 #include "interpreter/ByteCode.h"
-#include "parser/ASTAllocator.h"
 #if defined(ENABLE_CODE_CACHE)
 #include "codecache/CodeCache.h"
 #endif
-#if defined(ENABLE_WASM)
-#include "wasm.h"
-#endif
 
 #include <pthread.h>
 
 namespace Escargot {
 
-/////////////////////////////////////////////////
-// VMInstance Global Data
-/////////////////////////////////////////////////
-MAY_THREAD_LOCAL std::mt19937* VMInstance::g_randEngine;
-MAY_THREAD_LOCAL bf_context_t VMInstance::g_bfContext;
 #if defined(ENABLE_WASM)
 #ifndef ESCARGOT_WASM_GC_CHECK_INTERVAL
 #define ESCARGOT_WASM_GC_CHECK_INTERVAL 5000
 #endif
-MAY_THREAD_LOCAL WASMContext VMInstance::g_wasmContext;
-#endif
-MAY_THREAD_LOCAL ASTAllocator* VMInstance::g_astAllocator;
-MAY_THREAD_LOCAL WTF::BumpPointerAllocator* VMInstance::g_bumpPointerAllocator;
-
-void VMInstance::initialize()
-{
-    // g_randEngine
-    g_randEngine = new std::mt19937((unsigned int)time(NULL));
-
-    // g_bfContext
-    bf_context_init(&g_bfContext, [](void* opaque, void* ptr, size_t size) -> void* {
-        return realloc(ptr, size);
-    },
-                    nullptr);
-
-#if defined(ENABLE_WASM)
-    // g_wasmContext
-    g_wasmContext.engine = wasm_engine_new();
-    g_wasmContext.store = wasm_store_new(g_wasmContext.engine);
-    g_wasmContext.lastGCCheckTime = 0;
 #endif
 
-    // g_astAllocator
-    g_astAllocator = new ASTAllocator();
-
-    // g_bumpPointerAllocator
-    g_bumpPointerAllocator = new WTF::BumpPointerAllocator();
-
-    // initialize PointerValue tag values
-    // tag values should be initialized once and not changed
-    PointerValue::g_arrayObjectTag = ArrayObject().getTag();
-    PointerValue::g_arrayPrototypeObjectTag = ArrayPrototypeObject().getTag();
-    PointerValue::g_objectRareDataTag = ObjectRareData(nullptr).getTag();
-    PointerValue::g_doubleInEncodedValueTag = DoubleInEncodedValue(0).getTag();
-}
-
-void VMInstance::finalize()
-{
-    // this function should be invoked after full gc (Heap::finalize)
-    // because some registered gc-finalizers could use these global values
-
-    // g_randEngine does not need finalization
-    delete g_randEngine;
-    g_randEngine = nullptr;
-
-    // g_bfContext
-    bf_context_end(&g_bfContext);
-
-#if defined(ENABLE_WASM)
-    // g_wasmContext
-    wasm_store_delete(g_wasmContext.store);
-    wasm_engine_delete(g_wasmContext.engine);
-    g_wasmContext.store = nullptr;
-    g_wasmContext.engine = nullptr;
-    g_wasmContext.lastGCCheckTime = 0;
-#endif
-
-    // g_astAllocator
-    delete g_astAllocator;
-    g_astAllocator = nullptr;
-
-    // g_bumpPointerAllocator
-    delete g_bumpPointerAllocator;
-    g_bumpPointerAllocator = nullptr;
-}
-/////////////////////////////////////////////////
-
 Value VMInstance::functionPrototypeNativeGetter(ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea)
 {
     ASSERT(self->isFunctionObject());
@@ -245,9 +172,8 @@ void VMInstance::gcEventCallback(GC_EventType t, void* data)
         }
 #endif
 #if defined(ENABLE_WASM)
-        if (currentTick - g_wasmContext.lastGCCheckTime > ESCARGOT_WASM_GC_CHECK_INTERVAL) {
-            wasm_store_gc(g_wasmContext.store);
-            g_wasmContext.lastGCCheckTime = currentTick;
+        if (currentTick - ThreadLocal::wasmLastGCCheckTime() > ESCARGOT_WASM_GC_CHECK_INTERVAL) {
+            ThreadLocal::wasmGC(currentTick);
         }
 #endif
 #endif
@@ -314,7 +240,6 @@ void* VMInstance::operator new(size_t size)
         GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_regexpCache));
         GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_regexpOptionStringCache));
         GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_cachedUTC));
-        GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_platform));
         GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_jobQueue));
 #if defined(ENABLE_INTL)
         GC_set_bit(desc, GC_WORD_OFFSET(VMInstance, m_intlAvailableLocales));
@@ -368,7 +293,7 @@ VMInstance::~VMInstance()
 #endif
 }
 
-VMInstance::VMInstance(Platform* platform, const char* locale, const char* timezone, const char* baseCacheDir)
+VMInstance::VMInstance(const char* locale, const char* timezone, const char* baseCacheDir)
     : m_staticStrings(&m_atomicStringMap)
     , m_currentSandBox(nullptr)
     , m_isFinalized(false)
@@ -387,7 +312,6 @@ VMInstance::VMInstance(Platform* platform, const char* locale, const char* timez
     , m_promiseHook(nullptr)
     , m_promiseHookPublic(nullptr)
     , m_cachedUTC(nullptr)
-    , m_platform(platform)
 {
     GC_REGISTER_FINALIZER_NO_ORDER(this, [](void* obj, void*) {
         VMInstance* self = (VMInstance*)obj;
@@ -580,7 +504,7 @@ void VMInstance::clearCachesRelatedWithContext()
     // this lock should be released immediately (destructor may be called later)
     m_codeCache->clear();
 #endif
-    bf_clear_cache(&g_bfContext);
+    bf_clear_cache(ThreadLocal::bfContext());
 }
 
 void VMInstance::enterIdleMode()
@@ -645,7 +569,7 @@ void VMInstance::somePrototypeObjectDefineIndexedProperty(ExecutionState& state)
 void VMInstance::enqueueJob(Job* job)
 {
     m_jobQueue->enqueueJob(job);
-    m_platform->markJSJobEnqueued(job->relatedContext());
+    Global::platform()->markJSJobEnqueued(job->relatedContext());
 }
 
 bool VMInstance::hasPendingJob()
index cfd6d6b6869eb340e160d2edefbbbe183fac8db6..daf386f2363ff19d73ef8a55af50208a00131619 100644 (file)
 #ifndef __EscargotVMInstance__
 #define __EscargotVMInstance__
 
-#include "runtime/Platform.h"
+#include "runtime/SandBox.h"
 #include "runtime/AtomicString.h"
 #include "runtime/StaticStrings.h"
 #include "runtime/ToStringRecursionPreventer.h"
 
-#if defined(ENABLE_WASM)
-struct wasm_engine_t;
-struct wasm_store_t;
-struct WASMContext {
-    wasm_engine_t* engine;
-    wasm_store_t* store;
-    uint64_t lastGCCheckTime;
-};
-#endif
-
-namespace WTF {
-class BumpPointerAllocator;
-}
-
 namespace Escargot {
 
-class SandBox;
 class Context;
 class CodeBlock;
 class JobQueue;
 class Job;
-class ASTAllocator;
 class Symbol;
 class String;
 #if defined(ENABLE_COMPRESSIBLE_STRING)
@@ -93,53 +77,7 @@ class VMInstance : public gc {
     friend class ScriptParser;
     friend class SandBox;
 
-    /////////////////////////////////
-    // Global Data
-    // global values which should be initialized once and shared during the runtime
-    static MAY_THREAD_LOCAL std::mt19937* g_randEngine;
-    static MAY_THREAD_LOCAL bf_context_t g_bfContext;
-#if defined(ENABLE_WASM)
-    static MAY_THREAD_LOCAL WASMContext g_wasmContext;
-#endif
-
-    static MAY_THREAD_LOCAL ASTAllocator* g_astAllocator;
-    static MAY_THREAD_LOCAL WTF::BumpPointerAllocator* g_bumpPointerAllocator;
-    /////////////////////////////////
-
 public:
-    /////////////////////////////////
-    // Global Data Static Function
-    static void initialize();
-    static void finalize();
-    static std::mt19937& randEngine()
-    {
-        ASSERT(!!g_randEngine);
-        return *g_randEngine;
-    }
-    static bf_context_t* bfContext()
-    {
-        ASSERT(!!g_bfContext.realloc_func);
-        return &g_bfContext;
-    }
-#if defined(ENABLE_WASM)
-    static wasm_store_t* wasmStore()
-    {
-        ASSERT(!!g_wasmContext.store);
-        return g_wasmContext.store;
-    }
-#endif
-    static ASTAllocator* astAllocator()
-    {
-        ASSERT(!!g_astAllocator);
-        return g_astAllocator;
-    }
-    static WTF::BumpPointerAllocator* bumpPointerAllocator()
-    {
-        ASSERT(!!g_bumpPointerAllocator);
-        return g_bumpPointerAllocator;
-    }
-    /////////////////////////////////
-
     enum PromiseHookType {
         Init,
         Resolve,
@@ -149,7 +87,7 @@ public:
 
     typedef void (*PromiseHook)(ExecutionState& state, PromiseHookType type, PromiseObject* promise, const Value& parent, void* hook);
 
-    VMInstance(Platform* platform, const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr);
+    VMInstance(const char* locale = nullptr, const char* timezone = nullptr, const char* baseCacheDir = nullptr);
     ~VMInstance();
 
     void* operator new(size_t size);
@@ -259,11 +197,6 @@ public:
     }
 #endif
 
-    Platform* platform()
-    {
-        return m_platform;
-    }
-
     SandBox* currentSandBox()
     {
         return m_currentSandBox;
@@ -279,7 +212,6 @@ public:
         return m_regexpOptionStringCache;
     }
 
-
     void setOnDestroyCallback(void (*onVMInstanceDestroy)(VMInstance* instance, void* data), void* data)
     {
         m_onVMInstanceDestroy = onVMInstanceDestroy;
@@ -399,8 +331,6 @@ private:
 #endif
     DateObject* m_cachedUTC;
 
-    Platform* m_platform;
-
     // promise job queue
     JobQueue* m_jobQueue;
 
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBigIntValue.h
new file mode 100644 (file)
index 0000000..7e5c78a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedBigIntValue__
+#define __EscargotSerializedBigIntValue__
+
+#include "runtime/serialization/SerializedValue.h"
+#include "runtime/BigInt.h"
+
+namespace Escargot {
+
+class SerializedBigIntValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::BigInt;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        BigIntData d(m_value.data(), m_value.size());
+        return Value(new ::Escargot::BigInt(std::move(d)));
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        size_t s = m_value.size();
+        outputStream << s;
+        outputStream << std::endl;
+        for (size_t i = 0; i < s; i++) {
+            outputStream << m_value[i];
+        }
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        size_t s;
+        inputStream >> s;
+        std::string str;
+        str.reserve(s);
+
+        for (size_t i = 0; i < s; i++) {
+            char ch;
+            inputStream >> ch;
+            str.push_back(ch);
+        }
+
+        return std::unique_ptr<SerializedValue>(new SerializedBigIntValue(std::move(str)));
+    }
+
+    SerializedBigIntValue(std::string&& value)
+        : m_value(value)
+    {
+    }
+    std::string m_value;
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedBooleanValue.h
new file mode 100644 (file)
index 0000000..8778e36
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedBooleanValue__
+#define __EscargotSerializedBooleanValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedBooleanValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::Boolean;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value(m_value);
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        outputStream << m_value;
+        outputStream << std::endl;
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        bool v;
+        inputStream >> v;
+        return std::unique_ptr<SerializedValue>(new SerializedBooleanValue(v));
+    }
+
+    SerializedBooleanValue(bool value)
+        : m_value(value)
+    {
+    }
+
+    bool m_value;
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNullValue.h
new file mode 100644 (file)
index 0000000..327e0c6
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedNullValue__
+#define __EscargotSerializedNullValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedNullValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::Null;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value(Value::Null);
+    }
+
+protected:
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        return std::unique_ptr<SerializedValue>(new SerializedNullValue());
+    }
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedNumberValue.h
new file mode 100644 (file)
index 0000000..c70e174
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedNumberValue__
+#define __EscargotSerializedNumberValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedNumberValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::Number;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value(m_value);
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        outputStream << m_value;
+        outputStream << std::endl;
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        double v;
+        inputStream >> v;
+        return std::unique_ptr<SerializedValue>(new SerializedNumberValue(v));
+    }
+
+    SerializedNumberValue(double value)
+        : m_value(value)
+    {
+    }
+    double m_value;
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSharedArrayBufferObjectValue.h
new file mode 100644 (file)
index 0000000..786fb94
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#if defined(ENABLE_THREADING)
+
+#ifndef __EscargotSerializedSharedArrayBufferObjectValue__
+#define __EscargotSerializedSharedArrayBufferObjectValue__
+
+#include "runtime/serialization/SerializedValue.h"
+#include "runtime/SharedArrayBufferObject.h"
+
+namespace Escargot {
+
+class SerializedSharedArrayBufferObjectValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::SharedArrayBufferObject;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value(new ::Escargot::SharedArrayBufferObject(state, state.context()->globalObject()->sharedArrayBufferPrototype(), m_bufferData));
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        size_t ptr = reinterpret_cast<size_t>(m_bufferData);
+        outputStream << ptr;
+        outputStream << std::endl;
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        size_t ptr;
+        inputStream >> ptr;
+        SharedArrayBufferObjectBackingStoreData* data = reinterpret_cast<SharedArrayBufferObjectBackingStoreData*>(ptr);
+        return std::unique_ptr<SerializedValue>(new SerializedSharedArrayBufferObjectValue(data));
+    }
+
+    SerializedSharedArrayBufferObjectValue(SharedArrayBufferObjectBackingStoreData* bufferData)
+        : m_bufferData(bufferData)
+    {
+        m_bufferData->ref();
+    }
+
+    ~SerializedSharedArrayBufferObjectValue()
+    {
+        m_bufferData->deref();
+    }
+
+    SharedArrayBufferObjectBackingStoreData* m_bufferData;
+};
+
+} // namespace Escargot
+
+#endif
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedStringValue.h
new file mode 100644 (file)
index 0000000..6dda479
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedStringValue__
+#define __EscargotSerializedStringValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedStringValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::String;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value(String::fromUTF8(m_value.data(), m_value.size()));
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        size_t s = m_value.size();
+        outputStream << s;
+        outputStream << std::endl;
+        for (size_t i = 0; i < s; i++) {
+            outputStream << m_value[i];
+        }
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        size_t s;
+        inputStream >> s;
+        std::string str;
+        str.reserve(s);
+
+        for (size_t i = 0; i < s; i++) {
+            char ch;
+            inputStream >> ch;
+            str.push_back(ch);
+        }
+
+        return std::unique_ptr<SerializedValue>(new SerializedStringValue(std::move(str)));
+    }
+
+    SerializedStringValue(std::string&& value)
+        : m_value(value)
+    {
+    }
+    std::string m_value;
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedSymbolValue.h
new file mode 100644 (file)
index 0000000..f9d1b6e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedSymbolValue__
+#define __EscargotSerializedSymbolValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedSymbolValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::Symbol;
+    }
+
+    virtual Value toValue(ExecutionState& state) override
+    {
+        if (m_value) {
+            return Value(new ::Escargot::Symbol(
+                String::fromUTF8(m_value.value().data(), m_value.value().size())));
+        }
+        return Value(new ::Escargot::Symbol());
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) override
+    {
+        if (m_value) {
+            outputStream << true;
+            outputStream << std::endl;
+            size_t s = m_value.value().size();
+            outputStream << s;
+            outputStream << std::endl;
+            for (size_t i = 0; i < s; i++) {
+                outputStream << (m_value.value())[i];
+            }
+        } else {
+            outputStream << false;
+            outputStream << std::endl;
+        }
+    }
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        bool hasValue;
+        inputStream >> hasValue;
+        if (hasValue) {
+            size_t s;
+            inputStream >> s;
+            std::string str;
+            str.reserve(s);
+
+            for (size_t i = 0; i < s; i++) {
+                char ch;
+                inputStream >> ch;
+                str.push_back(ch);
+            }
+
+            return std::unique_ptr<SerializedValue>(new SerializedSymbolValue(std::move(str)));
+        }
+        return std::unique_ptr<SerializedValue>(new SerializedSymbolValue());
+    }
+
+    SerializedSymbolValue(std::string&& value)
+        : m_value(value)
+    {
+    }
+
+    SerializedSymbolValue()
+    {
+    }
+
+    Optional<std::string> m_value;
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedUndefinedValue.h
new file mode 100644 (file)
index 0000000..35f39a3
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedUndefinedValue__
+#define __EscargotSerializedUndefinedValue__
+
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class SerializedUndefinedValue : public SerializedValue {
+    friend class Serializer;
+
+public:
+    virtual Type type() override
+    {
+        return SerializedValue::Undefined;
+    }
+    virtual Value toValue(ExecutionState& state) override
+    {
+        return Value();
+    }
+
+protected:
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& inputStream)
+    {
+        return std::unique_ptr<SerializedValue>(new SerializedUndefinedValue());
+    }
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/SerializedValue.h
new file mode 100644 (file)
index 0000000..c83d5a7
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializedValue__
+#define __EscargotSerializedValue__
+
+#include "runtime/Value.h"
+
+namespace Escargot {
+
+class SerializedValue {
+    friend class Serializer;
+
+public:
+#define FOR_EACH_SERIALIZABLE_TYPE(F) \
+    F(Undefined)                      \
+    F(Null)                           \
+    F(Boolean)                        \
+    F(Number)                         \
+    F(String)                         \
+    F(Symbol)                         \
+    F(BigInt)
+
+    enum Type {
+#define DECLARE_SERIALIZABLE_TYPE(name) name,
+        FOR_EACH_SERIALIZABLE_TYPE(DECLARE_SERIALIZABLE_TYPE)
+#undef DECLARE_SERIALIZABLE_TYPE
+#if defined(ENABLE_THREADING)
+            SharedArrayBufferObject
+#endif
+    };
+    virtual ~SerializedValue() {}
+    virtual Type type() = 0;
+    virtual Value toValue(ExecutionState& state) = 0;
+
+    void serializeInto(std::ostringstream& outputStream)
+    {
+        serializeValueType(outputStream);
+        serializeValueData(outputStream);
+    }
+
+protected:
+    virtual void serializeValueData(std::ostringstream& outputStream) {}
+    void serializeValueType(std::ostringstream& outputStream)
+    {
+        outputStream << static_cast<char>(type());
+    }
+};
+
+} // namespace Escargot
+
+#endif
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.cpp
new file mode 100644 (file)
index 0000000..7759776
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#include "Escargot.h"
+#include "Serializer.h"
+
+#include "runtime/serialization/SerializedBigIntValue.h"
+#include "runtime/serialization/SerializedBooleanValue.h"
+#include "runtime/serialization/SerializedNullValue.h"
+#include "runtime/serialization/SerializedNumberValue.h"
+#include "runtime/serialization/SerializedSharedArrayBufferObjectValue.h"
+#include "runtime/serialization/SerializedStringValue.h"
+#include "runtime/serialization/SerializedSymbolValue.h"
+#include "runtime/serialization/SerializedUndefinedValue.h"
+
+namespace Escargot {
+
+std::unique_ptr<SerializedValue> Serializer::serialize(const Value& value)
+{
+    if (value.isUndefined()) {
+        return std::unique_ptr<SerializedValue>(new SerializedUndefinedValue());
+    } else if (value.isNull()) {
+        return std::unique_ptr<SerializedValue>(new SerializedNullValue());
+    } else if (value.isBoolean()) {
+        return std::unique_ptr<SerializedValue>(new SerializedBooleanValue(value.asBoolean()));
+    } else if (value.isNumber()) {
+        return std::unique_ptr<SerializedValue>(new SerializedNumberValue(value.asNumber()));
+    } else if (value.isString()) {
+        return std::unique_ptr<SerializedValue>(new SerializedStringValue(value.asString()->toNonGCUTF8StringData()));
+    } else if (value.isBigInt()) {
+        return std::unique_ptr<SerializedValue>(new SerializedBigIntValue(value.asBigInt()->toString()->toNonGCUTF8StringData()));
+    } else if (value.isSymbol()) {
+        if (value.asSymbol()->description()) {
+            return std::unique_ptr<SerializedValue>(new SerializedSymbolValue(value.asSymbol()->description()->toNonGCUTF8StringData()));
+        } else {
+            return std::unique_ptr<SerializedValue>(new SerializedSymbolValue());
+        }
+    } else if (value.isObject()) {
+#if defined(ENABLE_THREADING)
+        if (value.asObject()->isSharedArrayBufferObject()) {
+            return std::unique_ptr<SerializedValue>(new SerializedSharedArrayBufferObjectValue(
+                static_cast<SharedArrayBufferObjectBackingStoreData*>(value.asObject()->asSharedArrayBufferObject()->backingStore()->deleterData())));
+        }
+#endif
+    }
+
+    return nullptr;
+}
+
+bool Serializer::serializeInto(const Value& value, std::ostringstream& output)
+{
+    auto sv = serialize(value);
+    if (sv) {
+        sv->serializeInto(output);
+        return true;
+    }
+    return false;
+}
+
+std::unique_ptr<SerializedValue> Serializer::deserializeFrom(std::istringstream& input)
+{
+    unsigned char type;
+    input >> type;
+    switch (type) {
+#define DECLARE_SERIALIZABLE_TYPE(name) \
+    case SerializedValue::Type::name:   \
+        return Serialized##name##Value::deserializeFrom(input);
+        FOR_EACH_SERIALIZABLE_TYPE(DECLARE_SERIALIZABLE_TYPE)
+#undef DECLARE_SERIALIZABLE_TYPE
+#if defined(ENABLE_THREADING)
+    case SerializedValue::Type::SharedArrayBufferObject:
+        return SerializedSharedArrayBufferObjectValue::deserializeFrom(input);
+#endif
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+} // namespace Escargot
diff --git a/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h b/lwnode/code/escargotshim/deps/escargot/src/runtime/serialization/Serializer.h
new file mode 100644 (file)
index 0000000..f482f33
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#ifndef __EscargotSerializer__
+#define __EscargotSerializer__
+
+#include "runtime/Value.h"
+#include "runtime/serialization/SerializedValue.h"
+
+namespace Escargot {
+
+class Serializer {
+public:
+    // this function can return nullptr if serialize failed
+    static std::unique_ptr<SerializedValue> serialize(const Value& value);
+    // returns the serialization was successful
+    static bool serializeInto(const Value& value, std::ostringstream& output);
+
+    static std::unique_ptr<SerializedValue> deserializeFrom(std::istringstream& input);
+};
+
+} // namespace Escargot
+
+#endif
index a283fe7b92df711a98b3c59a4d595f862a782787..f30fef06d41b148862ae15b6764439315be77a41 100644 (file)
 
 #include <string.h>
 #include <vector>
+#include <thread>
+#include <mutex>
+#include <sstream>
+
+#include <sys/timeb.h>
+#include <sys/time.h>
+#include <unistd.h>
 
 #include "api/EscargotPublic.h"
 #include "malloc.h"
@@ -259,7 +266,12 @@ static ValueRef* builtinGc(ExecutionStateRef* state, ValueRef* thisValue, size_t
     return ValueRef::createUndefined();
 }
 
+PersistentRefHolder<ContextRef> createEscargotContext(VMInstanceRef* instance, bool isMainThread = true);
+
 #if defined(ESCARGOT_ENABLE_TEST)
+
+static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcName, bool shouldPrintScriptResult, bool isModule);
+
 static ValueRef* builtinUneval(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
 {
     if (argc) {
@@ -299,11 +311,9 @@ static ValueRef* builtinCreateNewGlobalObject(ExecutionStateRef* state, ValueRef
     return ContextRef::create(state->context()->vmInstance())->globalObject();
 }
 
-PersistentRefHolder<ContextRef> createEscargotContext(VMInstanceRef* instance);
-
 static ValueRef* builtin262CreateRealm(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
 {
-    auto newContext = createEscargotContext(state->context()->vmInstance());
+    auto newContext = createEscargotContext(state->context()->vmInstance(), false);
     return newContext->globalObject()->get(state, StringRef::createFromASCII("$262"));
 }
 
@@ -327,182 +337,218 @@ static ValueRef* builtin262IsHTMLDDA(ExecutionStateRef* state, ValueRef* thisVal
 {
     return ValueRef::createNull();
 }
-#endif
 
+struct WorkerThreadData {
+    std::string message;
+    bool running;
+    volatile bool ended;
 
-PersistentRefHolder<ContextRef> createEscargotContext(VMInstanceRef* instance)
+    WorkerThreadData()
+        : running(true)
+        , ended(false)
+    {
+    }
+};
+std::mutex workerMutex;
+std::vector<std::pair<std::thread, WorkerThreadData>> workerThreads;
+std::vector<std::string> messagesFromWorkers;
+
+static ValueRef* builtin262AgentStart(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
 {
-    PersistentRefHolder<ContextRef> context = ContextRef::create(instance);
+    std::string script = argv[0]->toString(state)->toStdUTF8String();
 
-    Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* {
-        ContextRef* context = state->context();
+    std::thread worker([](std::string script) {
+        Globals::initializeThread();
 
-        GlobalObjectProxyObjectRef* proxy = GlobalObjectProxyObjectRef::create(state, state->context()->globalObject(), [](ExecutionStateRef* state, GlobalObjectProxyObjectRef* proxy, GlobalObjectRef* targetGlobalObject, GlobalObjectProxyObjectRef::AccessOperationType operationType, OptionalRef<AtomicStringRef> nonIndexedStringPropertyNameIfExists) {
-            // TODO check security
-        });
-        context->setGlobalObjectProxy(proxy);
+        Memory::setGCFrequency(24);
 
+        PersistentRefHolder<VMInstanceRef> instance = VMInstanceRef::create();
+        PersistentRefHolder<ContextRef> context = createEscargotContext(instance.get(), false);
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "print"), builtinPrint, 1, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("print"), buildFunctionObjectRef, true, true, true);
-        }
+        evalScript(context.get(), StringRef::createFromUTF8(script.data(), script.size()),
+                   StringRef::createFromASCII("from main thread"), false, false);
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "load"), builtinLoad, 1, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("load"), buildFunctionObjectRef, true, true, true);
-        }
+        while (true) {
+            {
+                bool running = false;
+                std::lock_guard<std::mutex> guard(workerMutex);
+                for (size_t i = 0; i < workerThreads.size(); i++) {
+                    if (workerThreads[i].first.get_id() == std::this_thread::get_id()) {
+                        running = workerThreads[i].second.running;
+                        break;
+                    }
+                }
+                if (!running) {
+                    break;
+                }
+            }
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "read"), builtinRead, 1, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("read"), buildFunctionObjectRef, true, true, true);
-        }
+            // readmessage if exists
+            std::string message;
+            {
+                std::lock_guard<std::mutex> guard(workerMutex);
+                for (size_t i = 0; i < workerThreads.size(); i++) {
+                    if (workerThreads[i].first.get_id() == std::this_thread::get_id()) {
+                        message = std::move(workerThreads[i].second.message);
+                        break;
+                    }
+                }
+            }
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "run"), builtinRun, 1, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("run"), buildFunctionObjectRef, true, true, true);
-        }
+            if (message.length()) {
+                std::istringstream istream(message);
+                ValueRef* val1 = SerializerRef::deserializeFrom(context.get(), istream);
+                ValueRef* val2 = SerializerRef::deserializeFrom(context.get(), istream);
+
+                ValueRef* callback = (ValueRef*)context.get()->globalObject()->extraData();
+                if (callback) {
+                    Evaluator::execute(context.get(), [](ExecutionStateRef* state, ValueRef* callback, ValueRef* v1, ValueRef* v2) -> ValueRef* {
+                        ValueRef* argv[2] = { v1, v2 };
+                        return callback->call(state, ValueRef::createUndefined(), 2, argv);
+                    },
+                                       callback, val1, val2);
+                }
+            }
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true);
+            usleep(10 * 1000);
         }
 
-#if defined(ESCARGOT_ENABLE_TEST)
-        // There is no specific standard for the [@@toStringTag] property of global object.
-        // But "global" string is added here to pass legacy TCs
-        context->globalObject()->defineDataProperty(state, context->vmInstance()->toStringTagSymbol(), ObjectRef::DataPropertyDescriptor(AtomicStringRef::create(context, "global")->string(), (ObjectRef::PresentAttribute)(ObjectRef::NonWritablePresent | ObjectRef::NonEnumerablePresent | ObjectRef::ConfigurablePresent)));
+        context.release();
+        instance.release();
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "uneval"), builtinUneval, 1, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("uneval"), buildFunctionObjectRef, true, true, true);
-        }
+        Globals::finalizeThread();
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "drainJobQueue"), builtinDrainJobQueue, 0, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("drainJobQueue"), buildFunctionObjectRef, true, true, true);
+        std::lock_guard<std::mutex> guard(workerMutex);
+        for (size_t i = 0; i < workerThreads.size(); i++) {
+            if (workerThreads[i].first.get_id() == std::this_thread::get_id()) {
+                workerThreads[i].second.ended = true;
+            }
         }
+    },
+                       script);
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "addPromiseReactions"), builtinAddPromiseReactions, 3, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("addPromiseReactions"), buildFunctionObjectRef, true, true, true);
-        }
+    {
+        std::lock_guard<std::mutex> guard(workerMutex);
+        workerThreads.push_back(std::make_pair(std::move(worker), WorkerThreadData()));
+    }
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createNewGlobalObject"), builtinCreateNewGlobalObject, 0, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("createNewGlobalObject"), buildFunctionObjectRef, true, true, true);
-        }
+    return ValueRef::createUndefined();
+}
 
-        {
-            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "newGlobal"), builtinCreateNewGlobalObject, 0, true, false);
-            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("newGlobal"), buildFunctionObjectRef, true, true, true);
+static ValueRef* builtin262AgentBroadcast(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    std::ostringstream ostream;
+    if (argc > 0) {
+        SerializerRef::serializeInto(argv[0], ostream);
+    } else {
+        SerializerRef::serializeInto(ValueRef::createUndefined(), ostream);
+    }
+    if (argc > 1) {
+        SerializerRef::serializeInto(argv[1], ostream);
+    } else {
+        SerializerRef::serializeInto(ValueRef::createUndefined(), ostream);
+    }
+
+
+    std::string message(ostream.str());
+    {
+        std::lock_guard<std::mutex> guard(workerMutex);
+        for (size_t i = 0; i < workerThreads.size(); i++) {
+            workerThreads[i].second.message = message;
         }
+    }
 
-        // https://github.com/tc39/test262/blob/master/INTERPRETING.md
+    while (true) {
+        bool thereIsNoMessage = true;
         {
-            ObjectRef* dollor262Object = ObjectRef::create(state);
-
-            {
-                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false);
-                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true);
+            std::lock_guard<std::mutex> guard(workerMutex);
+            for (size_t i = 0; i < workerThreads.size(); i++) {
+                if (workerThreads[i].second.message.size()) {
+                    thereIsNoMessage = false;
+                    break;
+                }
             }
+        }
 
-            {
-                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createRealm"), builtin262CreateRealm, 0, true, false);
-                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("createRealm"), buildFunctionObjectRef, true, true, true);
-            }
+        if (thereIsNoMessage) {
+            break;
+        }
 
-            {
-                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "detachArrayBuffer"), builtin262DetachArrayBuffer, 1, true, false);
-                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("detachArrayBuffer"), buildFunctionObjectRef, true, true, true);
-            }
+        usleep(10 * 1000); // sleep 10ms
+    }
 
-            {
-                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "evalScript"), builtin262EvalScript, 1, true, false);
-                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("evalScript"), buildFunctionObjectRef, true, true, true);
-            }
 
-            {
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("global"), context->globalObjectProxy(), true, true, true);
-            }
+    return ValueRef::createUndefined();
+}
 
-            {
-                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "IsHTMLDDA"), builtin262IsHTMLDDA, 0, true, false);
-                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
-                buildFunctionObjectRef->setIsHTMLDDA();
-                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("IsHTMLDDA"), buildFunctionObjectRef, true, true, true);
-            }
+static ValueRef* builtin262AgentReport(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    std::string message;
+    if (argc > 0) {
+        message = argv[0]->toString(state)->toStdUTF8String();
+    }
+    std::lock_guard<std::mutex> guard(workerMutex);
+    messagesFromWorkers.push_back(message);
+    return ValueRef::createUndefined();
+}
 
-            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("$262"), dollor262Object, true, false, true);
+static ValueRef* builtin262AgentLeaving(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    std::lock_guard<std::mutex> guard(workerMutex);
+    for (size_t i = 0; i < workerThreads.size(); i++) {
+        if (workerThreads[i].first.get_id() == std::this_thread::get_id()) {
+            workerThreads[i].second.running = false;
+            break;
         }
-#endif
-        return ValueRef::createUndefined();
-    });
+    }
+    return ValueRef::createUndefined();
+}
 
-    return context;
+static ValueRef* builtin262AgentReceiveBroadcast(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    state->context()->globalObject()->setExtraData(argv[0]);
+    return ValueRef::createUndefined();
 }
 
-class ShellPlatform : public PlatformRef {
-public:
-    virtual void markJSJobEnqueued(ContextRef* relatedContext) override
-    {
-        // ignore. we always check pending job after eval script
+static ValueRef* builtin262AgentGetReport(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    std::lock_guard<std::mutex> guard(workerMutex);
+    if (messagesFromWorkers.size()) {
+        std::string message = messagesFromWorkers.front();
+        messagesFromWorkers.erase(messagesFromWorkers.begin());
+        return StringRef::createFromUTF8(message.data(), message.size());
+    } else {
+        return ValueRef::createNull();
     }
+}
 
-    static std::string dirnameOf(const std::string& fname)
-    {
-        size_t pos = fname.find_last_of("/");
-        if (std::string::npos == pos) {
-            pos = fname.find_last_of("\\/");
-        }
-        return (std::string::npos == pos)
-            ? ""
-            : fname.substr(0, pos);
-    }
+static ValueRef* builtin262AgentMonotonicNow(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return ValueRef::create((uint64_t)tv.tv_sec * 1000UL + tv.tv_usec / 1000UL);
+}
 
-    static std::string absolutePath(const std::string& referrerPath, const std::string& src)
-    {
-        std::string utf8MayRelativePath = dirnameOf(referrerPath) + "/" + src;
-        auto absPath = realpath(utf8MayRelativePath.data(), nullptr);
-        if (!absPath) {
-            return std::string();
-        }
-        std::string utf8AbsolutePath = absPath;
-        free(absPath);
+static ValueRef* builtin262AgentSleep(ExecutionStateRef* state, ValueRef* thisValue, size_t argc, ValueRef** argv, bool isConstructCall)
+{
+    double m = argv[0]->toNumber(state);
+    usleep(m * 1000.0);
+    return ValueRef::createUndefined();
+}
 
-        return utf8AbsolutePath;
-    }
+#endif
 
-    static std::string absolutePath(const std::string& src)
+class ShellPlatform : public PlatformRef {
+public:
+    virtual void markJSJobEnqueued(ContextRef* relatedContext) override
     {
-        auto absPath = realpath(src.data(), nullptr);
-        if (!absPath) {
-            return std::string();
-        }
-        std::string utf8AbsolutePath = absPath;
-        free(absPath);
-
-        return utf8AbsolutePath;
+        // ignore. we always check pending job after eval script
     }
 
-    std::vector<std::tuple<std::string /* abs path */, ContextRef*, PersistentRefHolder<ScriptRef>>> loadedModules;
     virtual LoadModuleResult onLoadModule(ContextRef* relatedContext, ScriptRef* whereRequestFrom, StringRef* moduleSrc) override
     {
         std::string referrerPath = whereRequestFrom->src()->toStdUTF8String();
+        auto& loadedModules = *reinterpret_cast<std::vector<std::tuple<std::string, ContextRef*, PersistentRefHolder<ScriptRef>>>*>(threadLocalCustomData());
 
         for (size_t i = 0; i < loadedModules.size(); i++) {
             if (std::get<2>(loadedModules[i]) == whereRequestFrom) {
@@ -545,6 +591,7 @@ public:
         } else {
             path = absolutePath(loadedModule->src()->toStdUTF8String());
         }
+        auto& loadedModules = *reinterpret_cast<std::vector<std::tuple<std::string, ContextRef*, PersistentRefHolder<ScriptRef>>>*>(threadLocalCustomData());
         loadedModules.push_back(std::make_tuple(path, relatedContext, PersistentRefHolder<ScriptRef>(loadedModule)));
     }
 
@@ -553,6 +600,53 @@ public:
         LoadModuleResult loadedModuleResult = onLoadModule(relatedContext, referrer, src);
         notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, loadedModuleResult);
     }
+
+    virtual void* allocateThreadLocalCustomData() override
+    {
+        return new std::vector<std::tuple<std::string /* abs path */, ContextRef*, PersistentRefHolder<ScriptRef>>>();
+    }
+
+    virtual void deallocateThreadLocalCustomData() override
+    {
+        delete reinterpret_cast<std::vector<std::tuple<std::string, ContextRef*, PersistentRefHolder<ScriptRef>>>*>(threadLocalCustomData());
+    }
+
+private:
+    std::string dirnameOf(const std::string& fname)
+    {
+        size_t pos = fname.find_last_of("/");
+        if (std::string::npos == pos) {
+            pos = fname.find_last_of("\\/");
+        }
+        return (std::string::npos == pos)
+            ? ""
+            : fname.substr(0, pos);
+    }
+
+    std::string absolutePath(const std::string& referrerPath, const std::string& src)
+    {
+        std::string utf8MayRelativePath = dirnameOf(referrerPath) + "/" + src;
+        auto absPath = realpath(utf8MayRelativePath.data(), nullptr);
+        if (!absPath) {
+            return std::string();
+        }
+        std::string utf8AbsolutePath = absPath;
+        free(absPath);
+
+        return utf8AbsolutePath;
+    }
+
+    std::string absolutePath(const std::string& src)
+    {
+        auto absPath = realpath(src.data(), nullptr);
+        if (!absPath) {
+            return std::string();
+        }
+        std::string utf8AbsolutePath = absPath;
+        free(absPath);
+
+        return utf8AbsolutePath;
+    }
 };
 
 static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcName, bool shouldPrintScriptResult, bool isModule)
@@ -622,6 +716,189 @@ static bool evalScript(ContextRef* context, StringRef* source, StringRef* srcNam
     return result;
 }
 
+
+PersistentRefHolder<ContextRef> createEscargotContext(VMInstanceRef* instance, bool isMainThread)
+{
+    PersistentRefHolder<ContextRef> context = ContextRef::create(instance);
+
+    Evaluator::execute(context, [](ExecutionStateRef* state, bool isMainThread) -> ValueRef* {
+        ContextRef* context = state->context();
+
+        GlobalObjectProxyObjectRef* proxy = GlobalObjectProxyObjectRef::create(state, state->context()->globalObject(), [](ExecutionStateRef* state, GlobalObjectProxyObjectRef* proxy, GlobalObjectRef* targetGlobalObject, GlobalObjectProxyObjectRef::AccessOperationType operationType, OptionalRef<AtomicStringRef> nonIndexedStringPropertyNameIfExists) {
+            // TODO check security
+        });
+        context->setGlobalObjectProxy(proxy);
+
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "print"), builtinPrint, 1, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("print"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "load"), builtinLoad, 1, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("load"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "read"), builtinRead, 1, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("read"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "run"), builtinRun, 1, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("run"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true);
+        }
+
+#if defined(ESCARGOT_ENABLE_TEST)
+        // There is no specific standard for the [@@toStringTag] property of global object.
+        // But "global" string is added here to pass legacy TCs
+        context->globalObject()->defineDataProperty(state, context->vmInstance()->toStringTagSymbol(), ObjectRef::DataPropertyDescriptor(AtomicStringRef::create(context, "global")->string(), (ObjectRef::PresentAttribute)(ObjectRef::NonWritablePresent | ObjectRef::NonEnumerablePresent | ObjectRef::ConfigurablePresent)));
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "uneval"), builtinUneval, 1, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("uneval"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "drainJobQueue"), builtinDrainJobQueue, 0, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("drainJobQueue"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "addPromiseReactions"), builtinAddPromiseReactions, 3, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("addPromiseReactions"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createNewGlobalObject"), builtinCreateNewGlobalObject, 0, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("createNewGlobalObject"), buildFunctionObjectRef, true, true, true);
+        }
+
+        {
+            FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "newGlobal"), builtinCreateNewGlobalObject, 0, true, false);
+            FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("newGlobal"), buildFunctionObjectRef, true, true, true);
+        }
+
+        // https://github.com/tc39/test262/blob/master/INTERPRETING.md
+        {
+            ObjectRef* dollor262Object = ObjectRef::create(state);
+
+            {
+                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "gc"), builtinGc, 0, true, false);
+                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("gc"), buildFunctionObjectRef, true, true, true);
+            }
+
+            {
+                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "createRealm"), builtin262CreateRealm, 0, true, false);
+                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("createRealm"), buildFunctionObjectRef, true, true, true);
+            }
+
+            {
+                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "detachArrayBuffer"), builtin262DetachArrayBuffer, 1, true, false);
+                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("detachArrayBuffer"), buildFunctionObjectRef, true, true, true);
+            }
+
+            {
+                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "evalScript"), builtin262EvalScript, 1, true, false);
+                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("evalScript"), buildFunctionObjectRef, true, true, true);
+            }
+
+            {
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("global"), context->globalObjectProxy(), true, true, true);
+            }
+
+            {
+                FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "IsHTMLDDA"), builtin262IsHTMLDDA, 0, true, false);
+                FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                buildFunctionObjectRef->setIsHTMLDDA();
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("IsHTMLDDA"), buildFunctionObjectRef, true, true, true);
+            }
+
+            if (Globals::supportsThreading()) {
+                ObjectRef* agentObject = ObjectRef::create(state);
+                if (isMainThread) {
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "start"), builtin262AgentStart, 1, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("start"), buildFunctionObjectRef, true, true, true);
+                    }
+
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "broadcast"), builtin262AgentBroadcast, 2, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("broadcast"), buildFunctionObjectRef, true, true, true);
+                    }
+
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "getReport"), builtin262AgentGetReport, 0, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("getReport"), buildFunctionObjectRef, true, true, true);
+                    }
+                } else {
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "leaving"), builtin262AgentLeaving, 0, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("leaving"), buildFunctionObjectRef, true, true, true);
+                    }
+
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "receiveBroadcast"), builtin262AgentReceiveBroadcast, 1, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("receiveBroadcast"), buildFunctionObjectRef, true, true, true);
+                    }
+
+                    {
+                        FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "report"), builtin262AgentReport, 1, true, false);
+                        FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                        agentObject->defineDataProperty(state, StringRef::createFromASCII("report"), buildFunctionObjectRef, true, true, true);
+                    }
+                }
+
+                {
+                    FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "monotonicNow"), builtin262AgentMonotonicNow, 0, true, false);
+                    FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                    agentObject->defineDataProperty(state, StringRef::createFromASCII("monotonicNow"), buildFunctionObjectRef, true, true, true);
+                }
+
+                {
+                    FunctionObjectRef::NativeFunctionInfo nativeFunctionInfo(AtomicStringRef::create(context, "sleep"), builtin262AgentSleep, 1, true, false);
+                    FunctionObjectRef* buildFunctionObjectRef = FunctionObjectRef::create(state, nativeFunctionInfo);
+                    agentObject->defineDataProperty(state, StringRef::createFromASCII("sleep"), buildFunctionObjectRef, true, true, true);
+                }
+
+                dollor262Object->defineDataProperty(state, StringRef::createFromASCII("agent"), agentObject, true, false, true);
+            }
+
+            context->globalObject()->defineDataProperty(state, StringRef::createFromASCII("$262"), dollor262Object, true, false, true);
+        }
+#endif
+        return ValueRef::createUndefined();
+    },
+                       isMainThread);
+
+    return context;
+}
+
 int main(int argc, char* argv[])
 {
 #ifndef NDEBUG
@@ -636,15 +913,11 @@ int main(int argc, char* argv[])
     mallopt(M_MMAP_MAX, 1024 * 1024);
 #endif
 
-    Globals::initialize();
+    Globals::initialize(new ShellPlatform());
 
     Memory::setGCFrequency(24);
 
-    ShellPlatform* platform = new ShellPlatform();
-    PersistentRefHolder<VMInstanceRef> instance = VMInstanceRef::create(platform);
-    instance->setOnVMInstanceDelete([](VMInstanceRef* instance) {
-        delete instance->platform();
-    });
+    PersistentRefHolder<VMInstanceRef> instance = VMInstanceRef::create();
     PersistentRefHolder<ContextRef> context = createEscargotContext(instance.get());
 
     if (getenv("GC_FREE_SPACE_DIVISOR") && strlen(getenv("GC_FREE_SPACE_DIVISOR"))) {
@@ -733,6 +1006,10 @@ int main(int argc, char* argv[])
         }
     }
 
+    if (runShell && !context->isDebuggerRunning()) {
+        printf("escargot version:%s, %s%s\n", Globals::version(), Globals::buildDate(), Globals::supportsThreading() ? "(supports threading)" : "");
+    }
+
     while (runShell) {
         static char buf[2048];
         printf("escargot> ");
@@ -744,6 +1021,30 @@ int main(int argc, char* argv[])
         evalScript(context, str, StringRef::createFromASCII("from shell input"), true, false);
     }
 
+#if defined(ESCARGOT_ENABLE_TEST)
+    while (true) {
+        bool everyThreadIsEnded = true;
+        {
+            std::lock_guard<std::mutex> guard(workerMutex);
+            for (auto& i : workerThreads) {
+                if (!i.second.ended) {
+                    everyThreadIsEnded = false;
+                    break;
+                }
+            }
+        }
+        if (everyThreadIsEnded) {
+            break;
+        }
+
+        usleep(10 * 1000);
+    }
+
+    for (auto& i : workerThreads) {
+        i.first.join();
+    }
+#endif
+
     context.release();
     instance.release();
 
diff --git a/lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h b/lwnode/code/escargotshim/deps/escargot/src/util/SpinLock.h
new file mode 100644 (file)
index 0000000..d96ef74
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
+ *  USA
+ */
+
+#if defined(ENABLE_THREADING)
+
+#ifndef __EscargotSpinLock__
+#define __EscargotSpinLock__
+
+#include <atomic>
+
+namespace Escargot {
+
+class SpinLock {
+    std::atomic_flag m_locked;
+
+public:
+    SpinLock()
+        : m_locked(0)
+    {
+    }
+
+    void lock()
+    {
+        while (m_locked.test_and_set(std::memory_order_acquire)) {
+        }
+    }
+
+    void unlock()
+    {
+        m_locked.clear(std::memory_order_release);
+    }
+};
+
+} // namespace Escargot
+
+#endif
+
+#endif
index 946a8e27883932ac87435dd43f8ae68e8f4a4286..ca87e12c1cac2efe3de437a98ca3bc17481a4e18 100644 (file)
@@ -23,6 +23,7 @@
 #include "wasm.h"
 #include "runtime/GlobalObject.h"
 #include "runtime/Context.h"
+#include "runtime/ThreadLocal.h"
 #include "runtime/VMInstance.h"
 #include "runtime/NativeFunctionObject.h"
 #include "runtime/ExtendedNativeFunctionObject.h"
@@ -124,7 +125,7 @@ static Value builtinWASMValidate(ExecutionState& state, Value thisValue, size_t
     wasm_byte_vec_new_uninitialized(&binary, byteLength);
     memcpy(binary.data, srcBuffer->data(), byteLength);
 
-    bool result = wasm_module_validate(VMInstance::wasmStore(), &binary);
+    bool result = wasm_module_validate(ThreadLocal::wasmStore(), &binary);
     wasm_byte_vec_delete(&binary);
 
     return Value(result);
@@ -346,7 +347,7 @@ static Value builtinWASMInstanceConstructor(ExecutionState& state, Value thisVal
 
     // Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
     own wasm_trap_t* trap = nullptr;
-    own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap);
+    own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
     wasm_extern_vec_delete(&imports);
 
     if (!instance) {
@@ -428,7 +429,7 @@ static Value builtinWASMMemoryConstructor(ExecutionState& state, Value thisValue
     own wasm_memorytype_t* memtype = wasm_memorytype_new(&limits);
 
     // Let (store, memaddr) be mem_alloc(store, memtype). If allocation fails, throw a RangeError exception.
-    own wasm_memory_t* memaddr = wasm_memory_new(VMInstance::wasmStore(), memtype);
+    own wasm_memory_t* memaddr = wasm_memory_new(ThreadLocal::wasmStore(), memtype);
     wasm_memorytype_delete(memtype);
 
     wasm_ref_t* memref = wasm_memory_as_ref(memaddr);
@@ -621,7 +622,7 @@ static Value builtinWASMTableConstructor(ExecutionState& state, Value thisValue,
     own wasm_tabletype_t* tabletype = wasm_tabletype_new(wasm_valtype_new(WASM_FUNCREF), &limits);
 
     // Let (store, tableaddr) be table_alloc(store, type).
-    own wasm_table_t* tableaddr = wasm_table_new(VMInstance::wasmStore(), tabletype, nullptr);
+    own wasm_table_t* tableaddr = wasm_table_new(ThreadLocal::wasmStore(), tabletype, nullptr);
     wasm_tabletype_delete(tabletype);
 
     wasm_ref_t* tableref = wasm_table_as_ref(tableaddr);
@@ -841,7 +842,7 @@ static Value builtinWASMGlobalConstructor(ExecutionState& state, Value thisValue
     own wasm_globaltype_t* globaltype = wasm_globaltype_new(wasm_valtype_new(valuetype), mut);
 
     // Let (store, globaladdr) be global_alloc(store, globaltype, value).
-    own wasm_global_t* globaladdr = wasm_global_new(VMInstance::wasmStore(), globaltype, &value);
+    own wasm_global_t* globaladdr = wasm_global_new(ThreadLocal::wasmStore(), globaltype, &value);
     wasm_globaltype_delete(globaltype);
 
     wasm_ref_t* globalref = wasm_global_as_ref(globaladdr);
index b076781a89ef616edc0f5672191d3c42709fc1ef..90b00c54b35fbc9c912ed6544f73d9895b7ac08e 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "Escargot.h"
 #include "wasm.h"
+#include "runtime/ThreadLocal.h"
 #include "runtime/VMInstance.h"
 #include "runtime/Job.h"
 #include "runtime/ArrayBufferObject.h"
@@ -121,7 +122,7 @@ static own wasm_func_t* wasmCreateHostFunction(ExecutionState& state, Object* fu
     own wasm_functype_t* functypeCopy = wasm_functype_copy(functype);
 
     WASMHostFunctionEnvironment* env = new WASMHostFunctionEnvironment(func, functypeCopy);
-    own wasm_func_t* funcaddr = wasm_func_new_with_env(VMInstance::wasmStore(), functypeCopy, callbackHostFunction, env, nullptr);
+    own wasm_func_t* funcaddr = wasm_func_new_with_env(ThreadLocal::wasmStore(), functypeCopy, callbackHostFunction, env, nullptr);
 
     state.context()->wasmEnvCache()->push_back(env);
 
@@ -146,7 +147,7 @@ static Value wasmInstantiateModule(ExecutionState& state, Value thisValue, size_
 
     // Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
     own wasm_trap_t* trap = nullptr;
-    own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap);
+    own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
     wasm_extern_vec_delete(&imports);
 
     if (!instance) {
@@ -187,7 +188,7 @@ Value WASMOperations::copyStableBufferBytes(ExecutionState& state, Value source)
             copyBuffer = ArrayBufferObject::cloneArrayBuffer(state, srcBuffer, 0, srcBuffer->byteLength(), state.context()->globalObject()->arrayBuffer());
         } else if (srcObject->isTypedArrayObject()) {
             TypedArrayObject* srcArray = srcObject->asTypedArrayObject();
-            ArrayBufferObject* srcBuffer = srcArray->buffer();
+            ArrayBuffer* srcBuffer = srcArray->buffer();
             copyBuffer = ArrayBufferObject::cloneArrayBuffer(state, srcBuffer, srcArray->byteOffset(), srcArray->arrayLength() * srcArray->elementSize(), state.context()->globalObject()->arrayBuffer());
         }
     }
@@ -212,7 +213,7 @@ Value WASMOperations::compileModule(ExecutionState& state, Value thisValue, size
     wasm_byte_vec_new_uninitialized(&binary, byteLength);
     memcpy(binary.data, srcBuffer->data(), byteLength);
 
-    own wasm_module_t* module = wasm_module_new(VMInstance::wasmStore(), &binary);
+    own wasm_module_t* module = wasm_module_new(ThreadLocal::wasmStore(), &binary);
     wasm_byte_vec_delete(&binary);
 
     if (!module) {
@@ -440,7 +441,7 @@ void WASMOperations::readImportsOfModule(ExecutionState& state, wasm_module_t* m
                 // Let (store, globaladdr) be global_alloc(store, const valtype, value).
                 // FIXME globaltype
                 own wasm_globaltype_t* globaltype = wasm_globaltype_new(wasm_valtype_new(wasm_valtype_kind(valtype)), WASM_CONST);
-                globaladdr = wasm_global_new(VMInstance::wasmStore(), globaltype, &value);
+                globaladdr = wasm_global_new(ThreadLocal::wasmStore(), globaltype, &value);
                 wasm_globaltype_delete(globaltype);
 
             } else if (v.isObject() && v.asObject()->isWASMGlobalObject()) {
@@ -526,7 +527,7 @@ Value WASMOperations::instantiateCoreModule(ExecutionState& state, Value thisVal
 
     // Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
     own wasm_trap_t* trap = nullptr;
-    own wasm_instance_t* instance = wasm_instance_new(VMInstance::wasmStore(), module, imports.data, &trap);
+    own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
     wasm_extern_vec_delete(&imports);
 
     if (!instance) {
@@ -561,7 +562,7 @@ Object* WASMOperations::instantiatePromiseOfModuleWithImportObject(ExecutionStat
 void WASMOperations::collectHeap()
 {
     // collect (GC) WASM Objects allocated inside WASM heap
-    wasm_store_gc(VMInstance::wasmStore());
+    wasm_store_gc(ThreadLocal::wasmStore());
 }
 
 } // namespace Escargot
index 89fb35df2f7475da2b5c8b115eb72fc2f1e62458..9e49187c5b0c88cc313507a35b102ec1c2107a36 100644 (file)
@@ -36,7 +36,14 @@ check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP)
 
 include(CheckTypeSize)
 check_type_size(ssize_t SSIZE_T)
-check_type_size(size_t SIZEOF_SIZE_T)
+#check_type_size(size_t SIZEOF_SIZE_T)
+
+# Escargot specific option (for the case of compilation to 32bit from 64bit)
+if (ESCARGOT_BUILD_32BIT)
+    set(SIZEOF_SIZE_T 4)
+else ()
+    set(SIZEOF_SIZE_T 8)
+endif ()
 
 set(WABT_ROOT ${PROJECT_SOURCE_DIR}/wabt)
 configure_file(${WABT_ROOT}/src/config.h.in ${PROJECT_SOURCE_DIR}/config.h)
@@ -141,10 +148,13 @@ set(WABT_SRC
 
 # disable -Wpointer-arith: this is a GCC extension, and doesn't work in MSVC.
 set(WASM_CXX_FLAGS_INTERNAL
-    -Wall -Wextra -Wno-unused-parameter -Wpointer-arith
-    -Wuninitialized -std=c++11 -Wold-style-cast -fno-exceptions -fPIC -fdata-sections -ffunction-sections
+    -Wall -Wextra -Werror -Wno-unused-parameter -Wpointer-arith
+    -Wuninitialized -fno-exceptions -fPIC -fdata-sections -ffunction-sections
 )
 
+# set c++ flags
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wold-style-cast")
+
 # Need to define __STDC_*_MACROS because C99 specifies that C++ shouldn't
 # define format (e.g. PRIu64) or limit (e.g. UINT32_MAX) macros without the
 # definition, and some libcs (e.g. glibc2.17 and earlier) follow that.
@@ -166,7 +176,7 @@ add_compile_options(${WASM_CXX_FLAGS})
 
 set(WASM_CFLAGS_FROM_ENV $ENV{CFLAGS})
 separate_arguments(WASM_CFLAGS_FROM_ENV)
-add_compile_options(${WASM_CXX_FLAGS_FROM_ENV})
+add_compile_options(${WASM_CFLAGS_FROM_ENV})
 
 # build wabt lib
 add_library(wabt STATIC ${WABT_SRC})
index 6942a2b23e8fb049a37fc966ecf9f954ebf76b6c..55114f502ce303265e6eb43f069e6546cba5a55f 100755 (executable)
@@ -1,11 +1,13 @@
 {
   'includes': ['common.gypi'],
   'variables': {
+    'target_arch%': '<(target_arch)',
+    'target_os%': '<(target_os)',
+    'build_host%': '<(build_host)',
+    'build_asan%': '<(build_asan)',
     'escargot_dir%': 'deps/escargot',
     "escargot_lib_type%": 'shared_lib', # static_lib | shared_lib
-    'build_asan%': '<(build_asan)',
-    'target_arch%': '<(target_arch)',
-#    'escargot_arch%': 'x64',
+    'escargot_threading%': '<(escargot_threading)',
     'conditions': [
       ['escargot_lib_type=="shared_lib"', {
         'lib_ext': '.so'
       ['target_arch=="x32"', {
         'target_arch': 'i686'
       }],
+      ['target_os=="tizen"', {
+        # tizen build host is fixed to gbs
+        'build_host': 'tizen_obs'
+      }],
     ],
   },
   'targets': [{
     'target_name': 'escargot',
     'type': 'none',
     'variables': {
+      'configs': '<!(["find", "<(escargot_dir)", \
+                              "-name", "CMakeLists.txt", "-o", "-name", "*.cmake"])',
+      'sources': '<!(["find", "<(escargot_dir)/src", \
+                              "<(escargot_dir)/third_party", \
+                              "-name", "*.cpp", "-o", "-name", "*.cc"])',
       'output_dir': '<(SHARED_INTERMEDIATE_DIR)/escargot',
       'escargot_libs': [
         '<(output_dir)/libescargot<(lib_ext)',
         '<(escargot_dir)/third_party/GCutil',
         '<(escargot_dir)/third_party/GCutil/bdwgc/include',
       ],
+      'conditions': [
+        ['escargot_threading==1', {
+          'defines':['ESCARGOT_THREADING']
+        }],
+      ],
     },
     'actions': [
       {
         'action_name': 'config escargot',
-        'inputs': [],
+        'inputs':  ['./escargot.gyp', '<@(configs)'],
         'outputs': ['<(output_dir)'],
         'action': [
           'cmake', '<(escargot_dir)', '-B<(output_dir)',
           '-DESCARGOT_MODE=<(build_mode)',
           '-DESCARGOT_HOST=<(build_host)',
           '-DESCARGOT_OUTPUT=<(escargot_lib_type)',
+          '-DESCARGOT_THREADING=<(escargot_threading)',
           '-DESCARGOT_ASAN=<(build_asan)',
         ],
       },
       {
         'action_name': 'build escargot',
-        'inputs': ['<(output_dir)'],
+        'inputs':  ['<(output_dir)', './escargot.gyp', '<@(sources)'],
         'outputs': ['<@(escargot_libs)'],
         'action': [
           'ninja', '-v', '-C', '<(output_dir)'
index 897675cca1439a02b7d80b7192fbad76e517904a..6d7c96738e4d283eff455ccdca79de47eea56989 100755 (executable)
@@ -17,6 +17,7 @@
       'include_dirs': [
         'src',
         'include',
+        'include/lwnode',
         '.',
         '<(SHARED_INTERMEDIATE_DIR)',
       ],
         'src/libplatform/tracing/trace-object.cc',
         'src/libplatform/tracing/trace-writer.cc',
         'src/api/utils/debug.cc',
-        'src/api/utils/flags.cc',
         'src/api/utils/gc.cc',
-        'src/api/utils/logger.cc',
+        'src/api/utils/smaps.cc',
+        'src/api/utils/logger/flags.cc',
+        'src/api/utils/logger/logger.cc',
         'src/api/arraybuffer-allocator.cc',
         'src/api/arraybuffer-deleter.cc',
         'src/api/es-helper.cc',
         'src/api/global-handles.cc',
         'src/api/function.cc',
         'src/api/object.cc',
+        'src/api/serializer.cc',
+        'src/api/stack-trace.cc',
+        'src/lwnode.cc',
       ],
+      'defines': ['V8_PROMISE_INTERNAL_FIELD_COUNT=1'],
       'cflags_cc!': ['-fno-exceptions'],
       'cflags_cc': [
         '-std=gnu++14',
           'LWNODE=1',
         ],
         'include_dirs': [
+          'src/api/utils/logger',
+          'include/lwnode',
           'include',
           '.',
         ],
+        'cflags_cc!': ['-fno-exceptions'],
+        'cflags_cc': ['-fexceptions'],
       },
       'conditions': [
         ['OS == "linux"', {
           ],
         }],
       ],
-      'actions': [
-        {
-          'action_name': 'escargotshim_js2c',
-          'process_outputs_as_sources': 1,
-          'javascript_files': [
-            'lib/stack_frame.js',
-          ],
-          'inputs': [
-            'tools/js2c.py',
-            '<@(_javascript_files)',
-          ],
-          'outputs': [
-            '<(SHARED_INTERMEDIATE_DIR)/escargot_natives.h',
-          ],
-          'action': [
-            'python',
-            '<@(_inputs)',
-            '--target',
-            '<@(_outputs)',
-          ],
-        },
-      ],
     },
   ],
 }
index e96870143e6d6c47314a71b64359235b4297202f..42d9ef16131f24a1efe8811ec1fe650961d98a18 100644 (file)
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <stdint.h>
-#include "../src/unimplemented.h"
 
 namespace v8 {
 class Isolate;
diff --git a/lwnode/code/escargotshim/include/lwnode/lwnode.h b/lwnode/code/escargotshim/include/lwnode/lwnode.h
new file mode 100644 (file)
index 0000000..d196252
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <v8.h>
+#include <string>
+
+namespace LWNode {
+
+void InitializeProcessMethods(v8::Local<v8::Object> target,
+                              v8::Local<v8::Context> context);
+
+bool dumpSelfMemorySnapshot();
+
+class Utils {
+ public:
+  // should return string buffer
+  typedef void* (*LoadCallback)(void* callbackData);
+  // should free memoryPtr
+  typedef void (*UnloadCallback)(void* memoryPtr, void* callbackData);
+
+  struct ReloadableSourceData {
+    void* preloadedData{nullptr};
+
+    const char* path() { return path_; }
+    size_t preloadedDataLength() { return preloadedDataLength_; }
+    static ReloadableSourceData* create(std::string sourcePath,
+                                        void* preloadedData,
+                                        size_t preloadedDataLength);
+
+   private:
+    char* path_{nullptr};
+    size_t preloadedDataLength_{0};
+    ReloadableSourceData() = default;
+  };
+
+  static v8::MaybeLocal<v8::String> NewReloadableStringFromOneByte(
+      v8::Isolate* isolate,
+      ReloadableSourceData* data,
+      LoadCallback loadCallback,
+      UnloadCallback unloadCallback);
+};
+
+}  // namespace LWNode
index b60ebe7b46301ad45c7db095679534b292714e4c..271fafd77cfe6bd1acca991eae1f518aad74ac64 100644 (file)
@@ -12155,6 +12155,8 @@ MaybeLocal<T> Isolate::GetDataFromSnapshotOnce(size_t index) {
 
 int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
     int64_t change_in_bytes) {
+// @lwnode
+#if 0
   typedef internal::Internals I;
   int64_t* external_memory = reinterpret_cast<int64_t*>(
       reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryOffset);
@@ -12182,6 +12184,8 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
     ReportExternalAllocationLimitReached();
   }
   return *external_memory;
+#endif
+  return 0;
 }
 
 Local<Value> Context::GetEmbedderData(int index) {
diff --git a/lwnode/code/escargotshim/lib/stack_frame.js b/lwnode/code/escargotshim/lib/stack_frame.js
deleted file mode 100644 (file)
index d899cc8..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function () {
-  // Simulate V8 JavaScript stack trace API
-  function StackFrame(func, funcName, fileName, lineNumber, columnNumber) {
-    this.column = columnNumber | 0;
-    this.lineNumber = lineNumber | 0;
-    this.scriptName = fileName | 'Unknown';
-    this.functionName = funcName | 'Unknown';
-    this.function = func | function () { };
-  }
-
-  StackFrame.prototype.getFunction = function () {
-    // TODO: Fix if .stack is called from different callsite
-    // from where Error() or Error.captureStackTrace was called
-    return this.function;
-  };
-
-  StackFrame.prototype.getTypeName = function () {
-    //TODO : Fix this
-    return this.functionName;
-  };
-
-  StackFrame.prototype.getMethodName = function () {
-    return this.functionName;
-  };
-
-  StackFrame.prototype.getFunctionName = function () {
-    return this.functionName;
-  };
-
-  StackFrame.prototype.getFileName = function () {
-    return this.scriptName;
-  };
-
-  StackFrame.prototype.getLineNumber = function () {
-    return this.lineNumber;
-  };
-
-  StackFrame.prototype.getColumnNumber = function () {
-    return this.column;
-  };
-
-  StackFrame.prototype.isEval = function () {
-    // TODO
-    return false;
-  };
-
-  StackFrame.prototype.isToplevel = function () {
-    // TODO
-    return false;
-  };
-
-  StackFrame.prototype.isNative = function () {
-    // TODO
-    return false;
-  };
-
-  StackFrame.prototype.isConstructor = function () {
-    // TODO
-    return false;
-  };
-
-  StackFrame.prototype.toString = function () {
-    return (this.functionName || 'Anonymous function') + ' (' +
-      this.scriptName + ':' + this.lineNumber + ':' + this.column + ')';
-  };
-
-  function captureStackTrace(err, func) {
-    // TODO: implement error stack
-    err.stack = [];
-    err.stack.push(
-      new StackFrame(func, undefined, undefined, undefined, undefined));
-    err.stack.push(
-      new StackFrame(func, undefined, undefined, undefined, undefined));
-    err.stack.push(
-      new StackFrame(func, undefined, undefined, undefined, undefined));
-  }
-
-  Error.captureStackTrace = captureStackTrace;
-
-})();
index 2fab46c24747d9f6f5dfb99ce0c9df9adb46d1e5..e3f9d8902c8272c9828b7ff1ca27eb69d2f126da 100644 (file)
@@ -18,6 +18,8 @@
 #include "api/utils.h"
 #include "base.h"
 
+#include <sstream>
+
 using namespace Escargot;
 using namespace EscargotShim;
 
@@ -106,7 +108,7 @@ bool Value::IsDataView() const {
 }
 
 bool Value::IsSharedArrayBuffer() const {
-  LWNODE_RETURN_FALSE;
+  return CVAL(this)->value()->isSharedArrayBufferObject();
 }
 
 bool Value::IsObject() const {
@@ -513,7 +515,8 @@ std::unique_ptr<v8::BackingStore> v8::BackingStore::Reallocate(
     v8::Isolate* isolate,
     std::unique_ptr<v8::BackingStore> backing_store,
     size_t byte_length) {
-  LWNODE_UNIMPLEMENT;
+  auto self = reinterpret_cast<BackingStoreRef*>(backing_store.get());
+  self->reallocate(byte_length);
   return backing_store;
 }
 
@@ -532,7 +535,7 @@ std::shared_ptr<v8::BackingStore> v8::ArrayBuffer::GetBackingStore() {
   if (esSelf->backingStore().hasValue()) {
     esBackingStore = esSelf->backingStore().value();
   } else {
-    esBackingStore = BackingStoreRef::create(lwIsolate->vmInstance(), 0);
+    esBackingStore = BackingStoreRef::create(0);
   }
 
   return std::shared_ptr<v8::BackingStore>(
@@ -1035,10 +1038,6 @@ Maybe<bool> v8::Object::DefineOwnProperty(v8::Local<v8::Context> context,
                                           v8::PropertyAttribute attributes) {
   API_ENTER_WITH_CONTEXT(context, Nothing<bool>());
 
-  if (attributes == None) {
-    return Set(context, key, value);
-  }
-
   auto r = ObjectRefHelper::defineDataProperty(
       CVAL(*context)->context()->get(),
       CVAL(this)->value()->asObject(),
@@ -1114,40 +1113,14 @@ Maybe<PropertyAttribute> v8::Object::GetPropertyAttributes(
   auto esSelf = CVAL(this)->value()->asObject();
   auto esKey = CVAL(*key)->value();
 
-  PropertyAttribute attr;
-  EvalResult r = Evaluator::execute(
-      esContext,
-      [](ExecutionStateRef* esState,
-         ObjectRef* esSelf,
-         ValueRef* esKey,
-         PropertyAttribute* attr) -> ValueRef* {
-        auto val = esSelf->getOwnPropertyDescriptor(esState, esKey);
-        bool isWritable =
-            val->asObject()
-                ->get(esState, StringRef::createFromASCII("writable"))
-                ->asBoolean();
-        bool isEnumerable =
-            val->asObject()
-                ->get(esState, StringRef::createFromASCII("enumerable"))
-                ->asBoolean();
-        bool isConfigurable =
-            val->asObject()
-                ->get(esState, StringRef::createFromASCII("configurable"))
-                ->asBoolean();
-
-        *attr = *attr | !isWritable ? PropertyAttribute::ReadOnly
-                                    : PropertyAttribute::None;
-        *attr = *attr | !isEnumerable ? PropertyAttribute::DontEnum
-                                      : PropertyAttribute::None;
-        *attr = *attr | !isConfigurable ? PropertyAttribute::DontDelete
-                                        : PropertyAttribute::None;
-        return val;
-      },
-      esSelf,
-      esKey,
-      &attr);
+  auto r = ObjectRefHelper::getPropertyAttributes(esContext, esSelf, esKey);
   API_HANDLE_EXCEPTION(r, lwIsolate, Nothing<PropertyAttribute>());
 
+  if (r.result->isUndefined()) {
+    return Just(PropertyAttribute::None);
+  }
+
+  PropertyAttribute attr = static_cast<PropertyAttribute>(r.result->asUInt32());
   return Just(attr);
 }
 
@@ -1465,7 +1438,7 @@ Maybe<bool> Object::SetAccessor(Local<Context> context,
   Local<Value> dataLocalValue;
   if (!data.ToLocal(&dataLocalValue)) {
     dataLocalValue =
-        Utils::NewLocal<Value>(lwIsolate->toV8(), lwIsolate->undefined());
+        Utils::NewLocal<Value>(lwIsolate->toV8(), lwIsolate->undefined_value());
   }
 
   return ObjectUtils::SetAccessor(
@@ -1555,12 +1528,39 @@ v8::Object::GetRealNamedPropertyAttributesInPrototypeChain(
 
 MaybeLocal<Value> v8::Object::GetRealNamedProperty(Local<Context> context,
                                                    Local<Name> key) {
-  LWNODE_RETURN_LOCAL(Value);
+  API_ENTER_WITH_CONTEXT(context, MaybeLocal<Value>());
+
+  auto r = ObjectRefHelper::getOwnProperty(VAL(*context)->context()->get(),
+                                           VAL(this)->value()->asObject(),
+                                           VAL(*key)->value());
+
+  API_HANDLE_EXCEPTION(r, lwIsolate, MaybeLocal<Value>());
+
+  if (r.result->isUndefined()) {
+    return MaybeLocal<Value>();
+  }
+
+  return Utils::NewLocal<Value>(lwIsolate->toV8(), r.result);
 }
 
 Maybe<PropertyAttribute> v8::Object::GetRealNamedPropertyAttributes(
-    Local<Context> context,
-    Local<Name> key){LWNODE_RETURN_MAYBE(PropertyAttribute)}
+    Local<Context> context, Local<Name> key) {
+  API_ENTER_WITH_CONTEXT(context, Nothing<PropertyAttribute>());
+
+  auto r =
+      ObjectRefHelper::getPropertyAttributes(VAL(*context)->context()->get(),
+                                             CVAL(this)->value()->asObject(),
+                                             CVAL(*key)->value(),
+                                             true);
+  API_HANDLE_EXCEPTION(r, lwIsolate, Nothing<PropertyAttribute>());
+
+  if (r.result->isUndefined()) {
+    return Just(PropertyAttribute::None);
+  }
+
+  auto attr = static_cast<ObjectRef::PresentAttribute>(r.result->asUInt32());
+  return Just(V8Helper::toPropertyAttribute(attr));
+}
 
 Local<v8::Object> v8::Object::Clone() {
   auto lwIsolate = IsolateWrap::GetCurrent();
@@ -1602,10 +1602,27 @@ Local<v8::Object> v8::Object::Clone() {
 
 Local<v8::Context> v8::Object::CreationContext() {
   auto lwIsolate = IsolateWrap::GetCurrent();
-  LWNODE_DCHECK_MSG(lwIsolate->getNumberOfContexts() == 1,
-                    "%zu",
-                    lwIsolate->getNumberOfContexts());
-  return v8::Utils::NewLocal(lwIsolate->toV8(), lwIsolate->GetCurrentContext());
+  auto esSelf = CVAL(this)->value()->asObject();
+
+  auto esVal = esSelf->creationContext();
+  if (!esVal.hasValue()) {
+    return Local<v8::Context>();
+  }
+
+  auto globalObjectData =
+      ObjectRefHelper::getExtraData(esVal.get()->globalObject())
+          ->asGlobalObjectData();
+
+  LWNODE_CHECK(globalObjectData->internalFieldCount() ==
+               GlobalObjectData::kInternalFieldCount);
+
+  auto lwCreationContext = reinterpret_cast<ContextWrap*>(
+      globalObjectData->internalField(GlobalObjectData::kContextWrapSlot));
+
+  return v8::Local<v8::Context>::New(
+      lwIsolate->toV8(),
+      reinterpret_cast<v8::Context*>(
+          EscargotShim::ValueWrap::createContext(lwCreationContext)));
 }
 
 int v8::Object::GetIdentityHash() {
@@ -1613,11 +1630,17 @@ int v8::Object::GetIdentityHash() {
 }
 
 bool v8::Object::IsCallable() {
-  LWNODE_RETURN_FALSE;
+  auto esSelf = CVAL(this)->value()->asObject();
+  return esSelf->isCallable();
 }
 
 bool v8::Object::IsConstructor() {
-  LWNODE_RETURN_FALSE;
+  auto esSelf = CVAL(this)->value()->asObject();
+  if (esSelf->isFunctionObject()) {
+    return esSelf->asFunctionObject()->isConstructor();
+  }
+
+  return false;
 }
 
 bool v8::Object::IsApiWrapper() {
@@ -1647,7 +1670,18 @@ MaybeLocal<Function> Function::New(Local<Context> context,
                                    int length,
                                    ConstructorBehavior behavior,
                                    SideEffectType side_effect_type) {
-  LWNODE_RETURN_LOCAL(Function);
+  API_ENTER_WITH_CONTEXT(context, MaybeLocal<Function>());
+
+  Local<FunctionTemplate> functionTemplate =
+      FunctionTemplate::New(lwIsolate->toV8(),
+                            callback,
+                            data,
+                            Local<Signature>(),
+                            length,
+                            behavior,
+                            side_effect_type);
+
+  return functionTemplate->GetFunction(context);
 }
 
 MaybeLocal<Object> Function::NewInstance(Local<Context> context,
@@ -1752,7 +1786,9 @@ MaybeLocal<v8::Value> Function::Call(Local<Context> context,
   return Utils::NewLocal<Value>(lwIsolate->toV8(), r.result);
 }
 
-void Function::SetName(v8::Local<v8::String> name) {}
+void Function::SetName(v8::Local<v8::String> name) {
+  LWNODE_ONCE(LWNODE_UNIMPLEMENT);
+}
 
 Local<Value> Function::GetName() const {
   LWNODE_RETURN_LOCAL(Value);
@@ -1813,7 +1849,7 @@ bool String::ContainsOnlyOneByte() const {
 
 int String::Utf8Length(Isolate* isolate) const {
   auto esString = CVAL(this)->value()->asString();
-  if (esString->has8BitContent()) {
+  if (StringRefHelper::isAsciiString(esString)) {
     return esString->length();
   } else {
     return esString->toStdUTF8String().length();
@@ -1885,7 +1921,8 @@ int String::WriteUtf8(Isolate* v8_isolate,
 
   auto esString = CVAL(this)->value()->asString();
   auto bufferData = esString->stringBufferAccessData();
-  if (bufferData.has8BitContent) {
+
+  if (StringRefHelper::isAsciiString(esString)) {
     byteLength = bufferData.length;
     int maxBytes = std::min(bufferCapacity, byteLength);
     memcpy(buffer, bufferData.buffer, maxBytes);
@@ -2079,13 +2116,13 @@ void String::ExternalStringResourceBase::operator delete(void* ptr) {
 Local<Value> Symbol::Description() const {
   auto lwIsolate = IsolateWrap::GetCurrent();
   auto esDescription = CVAL(this)->value()->asSymbol()->description();
-  return Utils::NewLocal<String>(lwIsolate->toV8(), esDescription);
+  return Utils::NewLocal<String>(lwIsolate->toV8(), esDescription.get());
 }
 
 Local<Value> Private::Name() const {
   auto lwIsolate = IsolateWrap::GetCurrent();
   auto esDescription = CVAL(this)->value()->asSymbol()->description();
-  return Utils::NewLocal<String>(lwIsolate->toV8(), esDescription);
+  return Utils::NewLocal<String>(lwIsolate->toV8(), esDescription.get());
 }
 
 template <typename T, typename F>
@@ -2149,30 +2186,66 @@ int v8::Object::InternalFieldCount() {
       CVAL(this)->value()->asObject());
 }
 
+static std::string toExtraDataString(const void* target,
+                                     int index,
+                                     const void* field) {
+  std::ostringstream oss;
+  ObjectData* data =
+      ObjectRefHelper::getExtraData(CVAL(target)->value()->asObject());
+
+  oss << CVAL(target)->getHandleInfoString();
+  oss << " fields (" << data << ")";
+  oss << " [" << index << "]";
+
+  if (field && CVAL(field)->isValid()) {
+    oss << " " << CVAL(field)->getHandleInfoString();
+  } else {
+    oss << " " << field;
+  }
+  return oss.str();
+}
+
 Local<Value> v8::Object::SlowGetInternalField(int index) {
   auto lwValue =
       ObjectRefHelper::getInternalField(CVAL(this)->value()->asObject(), index);
+
+  LWNODE_CALL_TRACE_ID(
+      OBJDATA, "%s", toExtraDataString(this, index, lwValue).c_str());
+
   return Utils::ToLocal<Value>(lwValue);
 }
 
 void v8::Object::SetInternalField(int index, v8::Local<Value> value) {
+  LWNODE_CALL_TRACE_ID(
+      OBJDATA, "%s", toExtraDataString(this, index, *value).c_str());
+
   ObjectRefHelper::setInternalField(
       CVAL(this)->value()->asObject(), index, VAL(*value));
 }
 
 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
-  return ObjectRefHelper::getInternalPointer(CVAL(this)->value()->asObject(),
-                                             index);
+  void* field = ObjectRefHelper::getInternalPointer(
+      CVAL(this)->value()->asObject(), index);
+
+  LWNODE_CALL_TRACE_ID(
+      OBJDATA, "%s", toExtraDataString(this, index, field).c_str());
+
+  return field;
 }
 
 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
+  LWNODE_CALL_TRACE_ID(
+      OBJDATA, "%s", toExtraDataString(this, index, value).c_str());
+
   ObjectRefHelper::setInternalPointer(
       CVAL(this)->value()->asObject(), index, value);
 }
 
 void v8::Object::SetAlignedPointerInInternalFields(int argc,
                                                    int indices[],
-                                                   void* values[]) {}
+                                                   void* values[]) {
+  LWNODE_RETURN_VOID;
+}
 
 // static void* ExternalValue(i::Object obj) {
 //   // Obscure semantics for undefined, but somehow checked in our unit
index 3b3cfd2c543f1e3b9069f53ece78e57c2c8ec00e..3a6e4e17d0dea7061c2574933a0e1a2e9d9bbc56 100644 (file)
@@ -29,17 +29,12 @@ namespace v8 {
 
 void v8::V8::InitializePlatform(Platform* platform) {
   /* NOTHING TO DO */
-  LWNODE_CALL_TRACE_GC_START();
   internal::V8::InitializePlatform(platform);
-  LWNODE_CALL_TRACE_GC_END();
 }
 
 void v8::V8::ShutdownPlatform() {
-  LWNODE_CALL_TRACE_GC_START();
-  MemoryUtil::gc();
   EscargotShim::Platform::Dispose();
   internal::V8::ShutdownPlatform();
-  LWNODE_CALL_TRACE_GC_END();
 }
 
 bool v8::V8::Initialize(const int build_config) {
@@ -309,8 +304,8 @@ Local<External> v8::External::New(Isolate* isolate, void* value) {
   auto esObject = ObjectRefHelper::create(esContext);
 
   auto data = new ExternalObjectData();
-  data->setInternalFieldCount(1);
-  data->setInternalField(0, value);
+  data->setInternalFieldCount(ExternalObjectData::kInternalFieldCount);
+  data->setInternalField(ExternalObjectData::kValueSlot, value);
 
   ObjectRefHelper::setExtraData(esObject, data);
 
@@ -1448,7 +1443,9 @@ v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents(bool externalize) {
   return ArrayBuffer::Contents();
 }
 
-void v8::ArrayBuffer::Detach() {}
+void v8::ArrayBuffer::Detach() {
+  CVAL(this)->value()->asArrayBufferObject()->detachArrayBuffer();
+}
 
 size_t v8::ArrayBuffer::ByteLength() const {
   return CVAL(this)->value()->asArrayBufferObject()->byteLength();
@@ -1504,8 +1501,7 @@ std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
     Isolate* isolate, size_t byte_length) {
   auto lwIsolate = IsolateWrap::GetCurrent();
 
-  BackingStoreRef* esBackingStore =
-      BackingStoreRef::create(lwIsolate->vmInstance(), byte_length);
+  BackingStoreRef* esBackingStore = BackingStoreRef::create(byte_length);
   lwIsolate->addBackingStore(esBackingStore);
 
   return std::unique_ptr<v8::BackingStore>(
@@ -1520,40 +1516,31 @@ std::unique_ptr<v8::BackingStore> v8::ArrayBuffer::NewBackingStore(
   auto lwIsolate = IsolateWrap::GetCurrent();
   auto lwContext = lwIsolate->GetCurrentContext();
 
-  BackingStoreRef* esBackingStore = nullptr;
-  EvalResult r = Evaluator::execute(
-      lwContext->get(),
-      [](ExecutionStateRef* esState,
-         BackingStoreRef** backingStore,
-         void* data,
-         size_t byteLength,
-         v8::BackingStore::DeleterCallback deleter,
-         void* deleterData) -> ValueRef* {
-        struct Params {
-          v8::BackingStore::DeleterCallback deleter;
-          void* deleterData;
-        };
-
-        Params* callbackData = new Params();
-        callbackData->deleter = deleter;
-        callbackData->deleterData = deleterData;
-        auto callback = [](void* data, size_t length, void* callbackData) {
-          Params* p = (Params*)callbackData;
-          p->deleter(data, length, p->deleterData);
-          delete p;
-        };
-
-        *backingStore =
-            BackingStoreRef::create(data, byteLength, callback, callbackData);
+  struct Params {
+    BackingStore::DeleterCallback deleter{nullptr};
+    void* deleter_data{nullptr};
+  };
+
+  Params* callbackData = new Params();
+  callbackData->deleter = deleter;
+  callbackData->deleter_data = deleter_data;
+
+  auto callback = [](void* data, size_t length, void* callbackData) {
+    Params* params = reinterpret_cast<Params*>(callbackData);
+    if (data) {
+      /*
+        @note
+
+        According to src/node_buffer.cc mention, V8 simply ignores the
+        BackingStore deleter callback if data == nullptr.
+      */
+      params->deleter(data, length, params->deleter_data);
+    }
+    delete params;
+  };
 
-        return ValueRef::createNull();
-      },
-      &esBackingStore,
-      data,
-      byte_length,
-      deleter,
-      deleter_data);
-  LWNODE_CHECK(esBackingStore);
+  BackingStoreRef* esBackingStore =
+      BackingStoreRef::create(data, byte_length, callback, callbackData);
 
   lwIsolate->addBackingStore(esBackingStore);
 
@@ -1569,7 +1556,6 @@ Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
 
 size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
   LWNODE_CALL_TRACE();
-  LWNODE_CHECK_NOT_NULL(dest);
 
   auto esArrayBufferView = CVAL(this)->value()->asArrayBufferView();
 
@@ -1577,6 +1563,8 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
     return 0;
   }
 
+  LWNODE_CHECK_NOT_NULL(dest);
+
   size_t byteLengthToCopy =
       std::min(byte_length, esArrayBufferView->byteLength());
 
@@ -1586,7 +1574,7 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
 }
 
 bool v8::ArrayBufferView::HasBuffer() const {
-  ArrayBufferObjectRef* esArrayBufferObject =
+  ArrayBufferRef* esArrayBufferObject =
       CVAL(this)->value()->asArrayBufferView()->buffer();
   return esArrayBufferObject != nullptr;
 }
@@ -1684,12 +1672,24 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents(
 }
 
 size_t v8::SharedArrayBuffer::ByteLength() const {
-  LWNODE_RETURN_0;
+  auto esSelf = CVAL(this)->value()->asSharedArrayBufferObject();
+  return esSelf->byteLength();
 }
 
 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate,
                                                     size_t byte_length) {
-  LWNODE_RETURN_LOCAL(SharedArrayBuffer);
+  API_ENTER_NO_EXCEPTION(isolate);
+  auto lwContext = lwIsolate->GetCurrentContext();
+
+  auto r = Evaluator::execute(
+      lwContext->get(),
+      [](ExecutionStateRef* state, size_t byteLength) -> ValueRef* {
+        return SharedArrayBufferObjectRef::create(state, byteLength);
+      },
+      byte_length);
+  LWNODE_CHECK(r.isSuccessful());
+
+  return Utils::NewLocal<SharedArrayBuffer>(isolate, r.result);
 }
 
 Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
@@ -1697,6 +1697,7 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
     void* data,
     size_t byte_length,
     ArrayBufferCreationMode mode) {
+  // Deprecate soon
   LWNODE_RETURN_LOCAL(SharedArrayBuffer);
 }
 
@@ -1714,7 +1715,13 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(
 
 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
     Isolate* isolate, size_t byte_length) {
-  LWNODE_RETURN_NULLPTR;
+  auto lwIsolate = IsolateWrap::GetCurrent();
+
+  BackingStoreRef* esBackingStore = BackingStoreRef::create(byte_length);
+  lwIsolate->addBackingStore(esBackingStore);
+
+  return std::unique_ptr<v8::BackingStore>(
+      reinterpret_cast<v8::BackingStore*>(esBackingStore));
 }
 
 std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
@@ -1722,7 +1729,32 @@ std::unique_ptr<v8::BackingStore> v8::SharedArrayBuffer::NewBackingStore(
     size_t byte_length,
     v8::BackingStore::DeleterCallback deleter,
     void* deleter_data) {
-  LWNODE_RETURN_NULLPTR;
+  auto lwIsolate = IsolateWrap::GetCurrent();
+
+  struct Params {
+    BackingStore::DeleterCallback deleter{nullptr};
+    void* deleterData{nullptr};
+  };
+
+  Params* callbackData = new Params();
+  callbackData->deleter = deleter;
+  callbackData->deleterData = deleter_data;
+
+  auto callback = [](void* data, size_t length, void* callbackData) {
+    Params* params = reinterpret_cast<Params*>(callbackData);
+    if (data) {
+      params->deleter(data, length, params->deleterData);
+    }
+    delete params;
+  };
+
+  auto esBackingStore =
+      BackingStoreRef::create(data, byte_length, callback, callbackData);
+
+  lwIsolate->addBackingStore(esBackingStore);
+
+  return std::unique_ptr<v8::BackingStore>(
+      reinterpret_cast<v8::BackingStore*>(esBackingStore));
 }
 
 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
@@ -1911,7 +1943,8 @@ v8::Local<v8::Context> Isolate::GetIncumbentContext() {
 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
   LWNODE_CALL_TRACE_ID(TRYCATCH);
   auto lwIsolate = IsolateWrap::GetCurrent();
-  auto esValue = CVAL(*value)->value();
+  auto esValue = value.IsEmpty() ? lwIsolate->undefined_value()->value()
+                                 : CVAL(*value)->value();
   lwIsolate->ScheduleThrow(esValue);
 
   return Utils::NewLocal<Value>(lwIsolate->toV8(), esValue);
index 46d855147a776abbe07a6a4f6da6b1d0368ed3d4..f9b7a941f8609a6ab684475b593e4803181a937e 100644 (file)
@@ -113,7 +113,8 @@ v8::Local<v8::Value> v8::TryCatch::ReThrow() {
     return v8::Local<v8::Value>();
   }
   rethrow_ = true;
-  return v8::Utils::ToLocal<Value>(IsolateWrap::fromV8(isolate_)->undefined());
+  return v8::Utils::ToLocal<Value>(
+      IsolateWrap::fromV8(isolate_)->undefined_value());
 }
 
 v8::Local<Value> v8::TryCatch::Exception() const {
@@ -169,6 +170,19 @@ void v8::TryCatch::SetCaptureMessage(bool value) {
 
 // --- M e s s a g e ---
 
+static bool hasStackTraceData(ValueRef* exception) {
+  if (!exception->isObject()) {
+    return false;
+  }
+
+  auto stackTrace = ExceptionObjectData::stackTrace(exception->asObject());
+  auto empty = stackTrace->empty();
+  if (empty) {
+    LWNODE_LOG_WARN("No StackTrace found");
+  }
+  return !empty;
+}
+
 Local<String> Message::Get() const {
   LWNODE_RETURN_LOCAL(String);
 }
@@ -207,15 +221,16 @@ ScriptOrigin Message::GetScriptOrigin() const {
 
 v8::Local<Value> Message::GetScriptResourceName() const {
   auto lwIsolate = IsolateWrap::GetCurrent();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return Utils::NewLocal<String>(lwIsolate->toV8(), StringRef::emptyString());
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  return Utils::NewLocal<String>(lwIsolate->toV8(), top->src);
+  return Utils::NewLocal<String>(lwIsolate->toV8(), top->src());
 }
 
 v8::Local<v8::StackTrace> Message::GetStackTrace() const {
@@ -224,44 +239,44 @@ v8::Local<v8::StackTrace> Message::GetStackTrace() const {
 
 Maybe<int> Message::GetLineNumber(Local<Context> context) const {
   auto lwIsolate = CVAL(*context)->context()->GetIsolate();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return Just<int>(0);
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  return Just<int>(top->loc.line);
+  return Just<int>(top->loc().line);
 }
 
 int Message::GetStartPosition() const {
   auto lwIsolate = IsolateWrap::GetCurrent();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return 0;
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  return top->loc.index;
+  return top->loc().index;
 }
 
 int Message::GetEndPosition() const {
   auto lwIsolate = IsolateWrap::GetCurrent();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return 0;
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  return top->loc.index + 1;
+  return top->loc().index + 1;
 }
 
 int Message::ErrorLevel() const {
@@ -285,16 +300,16 @@ int Message::GetWasmFunctionIndex() const {
 
 Maybe<int> Message::GetStartColumn(Local<Context> context) const {
   auto lwIsolate = CVAL(*context)->context()->GetIsolate();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return Nothing<int>();
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  return Just<int>(top->loc.column - 1);
+  return Just<int>(top->loc().column - 1);
 }
 
 int Message::GetEndColumn() const {
@@ -303,16 +318,16 @@ int Message::GetEndColumn() const {
 
 Maybe<int> Message::GetEndColumn(Local<Context> context) const {
   auto lwIsolate = CVAL(*context)->context()->GetIsolate();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return Nothing<int>();
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  int endCol = top->loc.column;
+  int endCol = top->loc().column;
 
   return Just<int>(endCol);
 }
@@ -327,20 +342,20 @@ bool Message::IsOpaque() const {
 
 MaybeLocal<String> Message::GetSourceLine(Local<Context> context) const {
   auto lwIsolate = CVAL(*context)->context()->GetIsolate();
-  auto stackTrace =
-      ExceptionObjectData::stackTrace(lwIsolate->pending_exception());
 
-  if (stackTrace->empty()) {
-    LWNODE_LOG_WARN("No StackTrace found");
+  if (!hasStackTraceData(lwIsolate->pending_exception())) {
     return Utils::NewLocal<String>(lwIsolate->toV8(), StringRef::emptyString());
   }
 
+  auto stackTrace = ExceptionObjectData::stackTrace(
+      lwIsolate->pending_exception()->asObject());
+
   auto top = stackTrace->front();
-  std::string code = top->sourceCode->toStdUTF8String();
+  std::string code = top->sourceCode()->toStdUTF8String();
   std::stringstream ss(code);
   std::string line;
   for (size_t i = 1; std::getline(ss, line); i++) {
-    if (i == top->loc.line) {
+    if (i == top->loc().line) {
       break;
     }
   }
index eddef5191923636180063a1a1e5c1debce97312e..97c07efdf6da84d1871c0935b4c66a471f7906a8 100644 (file)
@@ -198,7 +198,7 @@ Maybe<bool> Module::InstantiateModule(Local<Context> context,
 MaybeLocal<Value> Module::Evaluate(Local<Context> context) {
   LWNODE_ONCE(LWNODE_UNIMPLEMENT_WORKAROUND);
   API_ENTER_WITH_CONTEXT(context, MaybeLocal<Value>());
-  return v8::Utils::ToLocal<Value>(lwIsolate->undefined());
+  return v8::Utils::ToLocal<Value>(lwIsolate->undefined_value());
 }
 
 Local<Module> Module::CreateSyntheticModule(
@@ -443,7 +443,7 @@ uint32_t ScriptCompiler::CachedDataVersionTag() {
 #ifndef NDEBUG
 static size_t s_track_data_size;
 #define TRACK_MSG_FMT                                                          \
-  "total size of new CachedData: " COLOR_GREEN "%zuB" COLOR_RESET
+  "total size of new CachedData: " CLR_GREEN "%zuB" CLR_RESET
 #endif
 
 ScriptCompiler::CachedData* ScriptCompiler::CreateCodeCache(
index 4d2d2246f4612b08c29dd86fa3488f4ab84e90a3..9d3d5cef880f6c3a088021508da84b3190de96ab 100644 (file)
@@ -41,57 +41,69 @@ Maybe<uint32_t> ValueSerializer::Delegate::GetWasmModuleTransferId(
 void* ValueSerializer::Delegate::ReallocateBufferMemory(void* old_buffer,
                                                         size_t size,
                                                         size_t* actual_size) {
-  LWNODE_RETURN_NULLPTR;
+  *actual_size = size;
+  return realloc(old_buffer, size);
 }
 
 void ValueSerializer::Delegate::FreeBufferMemory(void* buffer) {
-  LWNODE_UNIMPLEMENT;
+  return free(buffer);
 }
 
-// struct ValueSerializer::PrivateData {
-//   LWNODE_UNIMPLEMENT;
-// };
+struct ValueSerializer::PrivateData {
+  explicit PrivateData(Isolate* i, ValueSerializer::Delegate* delegate)
+      : isolate(i), serializer(i, delegate) {}
+  Isolate* isolate;
+  EscargotShim::ValueSerializer serializer;
+};
 
 ValueSerializer::ValueSerializer(Isolate* isolate)
     : ValueSerializer(isolate, nullptr) {
   LWNODE_UNIMPLEMENT;
 }
 
-ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate) {
-  LWNODE_UNIMPLEMENT;
-}
-// : private_(
-//       new PrivateData(reinterpret_cast<i::Isolate*>(isolate),
-//       delegate)) {}
+ValueSerializer::ValueSerializer(Isolate* isolate, Delegate* delegate)
+    : private_(new PrivateData(isolate, delegate)) {}
 
 ValueSerializer::~ValueSerializer() {
-  LWNODE_UNIMPLEMENT;
+  delete private_;
 }
 
 void ValueSerializer::WriteHeader() {
-  LWNODE_UNIMPLEMENT;
+  private_->serializer.WriteHeader();
 }
 
 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {}
 
 Maybe<bool> ValueSerializer::WriteValue(Local<Context> context,
-                                        Local<Value> value){
-    LWNODE_RETURN_MAYBE(bool)}
+                                        Local<Value> value) {
+  bool result = private_->serializer.WriteValue(CVAL(*value)->value());
+  return Just(result);
+}
 
 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
   return std::make_pair(nullptr, 0);
 }
 
 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
-                                          Local<ArrayBuffer> array_buffer) {}
+                                          Local<ArrayBuffer> array_buffer) {
+  LWNODE_RETURN_VOID;
+}
 
-void ValueSerializer::WriteUint32(uint32_t value) {}
+void ValueSerializer::WriteUint32(uint32_t value) {
+  LWNODE_RETURN_VOID;
+}
 
-void ValueSerializer::WriteUint64(uint64_t value) {}
+void ValueSerializer::WriteUint64(uint64_t value) {
+  LWNODE_RETURN_VOID;
+}
 
-void ValueSerializer::WriteDouble(double value) {}
+void ValueSerializer::WriteDouble(double value) {
+  LWNODE_RETURN_VOID;
+}
 
-void ValueSerializer::WriteRawBytes(const void* source, size_t length) {}
+void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
+  LWNODE_RETURN_VOID;
+}
 
 MaybeLocal<Object> ValueDeserializer::Delegate::ReadHostObject(
     Isolate* v8_isolate){LWNODE_RETURN_LOCAL(Object)}
@@ -109,21 +121,29 @@ struct ValueDeserializer::PrivateData {};
 ValueDeserializer::ValueDeserializer(Isolate* isolate,
                                      const uint8_t* data,
                                      size_t size)
-    : ValueDeserializer(isolate, data, size, nullptr) {}
+    : ValueDeserializer(isolate, data, size, nullptr) {
+  LWNODE_RETURN_VOID;
+}
 
 ValueDeserializer::ValueDeserializer(Isolate* isolate,
                                      const uint8_t* data,
                                      size_t size,
-                                     Delegate* delegate) {}
+                                     Delegate* delegate) {
+  LWNODE_RETURN_VOID;
+}
 
-ValueDeserializer::~ValueDeserializer() {}
+ValueDeserializer::~ValueDeserializer() {
+  LWNODE_RETURN_VOID;
+}
 
 Maybe<bool> ValueDeserializer::ReadHeader(Local<Context> context) {
   LWNODE_RETURN_MAYBE(bool)
 }
 
 void ValueDeserializer::SetSupportsLegacyWireFormat(
-    bool supports_legacy_wire_format) {}
+    bool supports_legacy_wire_format) {
+  LWNODE_RETURN_VOID;
+}
 
 uint32_t ValueDeserializer::GetWireFormatVersion() const {
   LWNODE_RETURN_0;
@@ -134,10 +154,14 @@ MaybeLocal<Value> ValueDeserializer::ReadValue(Local<Context> context) {
 }
 
 void ValueDeserializer::TransferArrayBuffer(uint32_t transfer_id,
-                                            Local<ArrayBuffer> array_buffer) {}
+                                            Local<ArrayBuffer> array_buffer) {
+  LWNODE_RETURN_VOID;
+}
 
 void ValueDeserializer::TransferSharedArrayBuffer(
-    uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) {}
+    uint32_t transfer_id, Local<SharedArrayBuffer> shared_array_buffer) {
+  LWNODE_RETURN_VOID;
+}
 
 bool ValueDeserializer::ReadUint32(uint32_t* value) {
   LWNODE_RETURN_FALSE;
index 8f6801b5e7155aac4567e75820ee3669d116e58b..5408749c0494bc428c6b272a764bd6e62d696eb1 100644 (file)
@@ -60,7 +60,9 @@ void Template::Set(v8::Local<Name> name,
 
 void Template::SetPrivate(v8::Local<Private> name,
                           v8::Local<Data> value,
-                          v8::PropertyAttribute attribute) {}
+                          v8::PropertyAttribute attribute) {
+  LWNODE_RETURN_VOID;
+}
 
 void Template::SetAccessorProperty(v8::Local<v8::Name> name,
                                    v8::Local<FunctionTemplate> getter,
@@ -114,15 +116,30 @@ static ValueRef* FunctionTemplateNativeFunction(
   LWNODE_DCHECK_NOT_NULL(callee->extraData());
   auto fnData = FunctionData::toFunctionData(callee->extraData());
 
+  LWNODE_CALL_TRACE_ID(TEMPLATE,
+                       "es: %p newTarget: %s",
+                       thisValue,
+                       strBool(newTarget.hasValue()));
+
+  auto lwIsolate = IsolateWrap::GetCurrent();
   if (!fnData->checkSignature(state, thisValue)) {
-    IsolateWrap::GetCurrent()->ScheduleThrow(TypeErrorObjectRef::create(
+    lwIsolate->ScheduleThrow(TypeErrorObjectRef::create(
         state, StringRef::createFromASCII("Illegal invocation")));
+    lwIsolate->Throw(state);
     LWNODE_DLOG_ERROR("Signature mismatch!");
     return ValueRef::createUndefined();
   }
 
+  auto thisObject = thisValue->asObject();
+  if (newTarget.hasValue() && ObjectRefHelper::hasExtraData(thisObject)) {
+    auto objectData = ObjectRefHelper::getExtraData(thisObject)->clone();
+    objectData->setInstanceTemplate(fnData->instanceTemplate());
+    ObjectRefHelper::setExtraData(thisObject, objectData, true);
+  }
+
   Local<Value> result;
   if (fnData->callback()) {
+    LWNODE_CALL_TRACE_ID(TEMPLATE, "> Call JS callback");
     FunctionCallbackInfoWrap info(fnData->isolate(),
                                   thisValue,
                                   thisValue,
@@ -131,16 +148,20 @@ static ValueRef* FunctionTemplateNativeFunction(
                                   argc,
                                   argv);
     fnData->callback()(info);
+    if (lwIsolate->has_scheduled_exception()) {
+      lwIsolate->Throw(state);
+    }
     result = info.GetReturnValue().Get();
-    // TODO: error check from 'state'
   }
 
   if (newTarget.hasValue()) {
     return thisValue;
   }
+
   if (!result.IsEmpty()) {
     return VAL(*result)->value();
   }
+
   return ValueRef::createUndefined();
 }
 
@@ -160,7 +181,7 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
     LWNODE_ONCE(LWNODE_DLOG_WARN("@ignored/SideEffectType::kHasSideEffect"));
   }
 
-  API_ENTER_NO_EXCEPTION(isolate);
+  API_ENTER_NO_EXCEPTION(isolate, TEMPLATE);
   bool isConstructor = false;
   if (behavior == ConstructorBehavior::kAllow) {
     isConstructor = true;
@@ -173,9 +194,10 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
                                   isConstructor,  // isConstruction
                                   FunctionTemplateNativeFunction);  // fn
 
-  FunctionTemplateRefHelper::setInstanceExtraData(
-      esFunctionTemplate,
-      new FunctionData(isolate, *callback, *data, *signature));
+  auto functionData = new FunctionData(isolate, *callback, *data, *signature);
+  functionData->setInstanceTemplate(esFunctionTemplate);
+  FunctionTemplateRefHelper::setInstanceExtraData(esFunctionTemplate,
+                                                  functionData);
 
   return Utils::NewLocal(isolate, esFunctionTemplate);
 }
@@ -225,7 +247,8 @@ Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
 }
 
 void FunctionTemplate::SetLength(int length) {
-  LWNODE_RETURN_VOID;
+  FunctionTemplateRef* self = CVAL(this)->ftpl();
+  self->setLength(length);
 }
 
 void FunctionTemplate::SetClassName(Local<String> name) {
@@ -261,7 +284,7 @@ void FunctionTemplate::RemovePrototype() {
 }
 
 MaybeLocal<v8::Function> FunctionTemplate::GetFunction(Local<Context> context) {
-  API_ENTER_WITH_CONTEXT(context, MaybeLocal<Function>());
+  API_ENTER_WITH_CONTEXT(context, MaybeLocal<Function>(), TEMPLATE);
   auto esContext = lwIsolate->GetCurrentContext()->get();
   auto esFunctionTemplate = CVAL(this)->ftpl();
 
@@ -280,27 +303,34 @@ bool FunctionTemplate::HasInstance(v8::Local<v8::Value> value) {
   if (!esValue->isObject()) {
     return false;
   }
-  auto esTemplateObject = CVAL(this)->ftpl()->instantiate(esContext);
+  auto esObject = esValue->asObject();
 
-  auto r = Evaluator::execute(
-      esContext,
-      [](ExecutionStateRef* esState,
-         ValueRef* esValue,
-         ObjectRef* esTemplateObject) -> ValueRef* {
-        return ValueRef::create(esValue->instanceOf(esState, esTemplateObject));
-      },
-      esValue,
-      esTemplateObject);
-  LWNODE_CHECK(r.isSuccessful());
+  if (!ObjectRefHelper::hasExtraData(esObject)) {
+    return false;
+  }
+
+  auto esSelf = CVAL(this)->ftpl();
+  auto tpl = ObjectRefHelper::getExtraData(esObject)->instanceTemplate();
+  if (esSelf == tpl) {
+    return true;
+  }
+
+  auto parent = tpl->parent();
+  while (parent.hasValue()) {
+    if (esSelf == parent.value()) {
+      return true;
+    }
+    parent = parent->parent();
+  }
 
-  return r.result->asBoolean();
+  return false;
 }
 
 // --- O b j e c t T e m p l a t e ---
 
 Local<ObjectTemplate> ObjectTemplate::New(
     Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
-  API_ENTER_NO_EXCEPTION(isolate);
+  API_ENTER_NO_EXCEPTION(isolate, TEMPLATE);
 
   return Utils::NewLocal(isolate, ObjectTemplateRef::create());
 }
@@ -353,6 +383,7 @@ void ObjectTemplate::SetAccessor(v8::Local<String> name,
                                  v8::Local<AccessorSignature> signature,
                                  SideEffectType getter_side_effect_type,
                                  SideEffectType setter_side_effect_type) {
+  // @note AccessControl is not considered.
   ObjectTemplateUtils::SetAccessor(CVAL(this)->otpl(),
                                    IsolateWrap::GetCurrent(),
                                    name,
@@ -371,6 +402,7 @@ void ObjectTemplate::SetAccessor(v8::Local<Name> name,
                                  v8::Local<AccessorSignature> signature,
                                  SideEffectType getter_side_effect_type,
                                  SideEffectType setter_side_effect_type) {
+  // @note AccessControl is not considered.
   ObjectTemplateUtils::SetAccessor(CVAL(this)->otpl(),
                                    IsolateWrap::GetCurrent(),
                                    name,
@@ -487,6 +519,20 @@ void ObjectTemplate::SetHandler(
       handlerConfiguration->m_namedPropertyHandler.query(v8PropertyName, info);
       Local<Value> ret = info.GetReturnValue().Get();
       if (info.hasReturnValue()) {
+        bool hasNone = (handlerConfiguration->m_namedPropertyHandler.flags ==
+                        PropertyHandlerFlags::kNone);
+        bool hasNoSideEffect =
+            (static_cast<int>(
+                 handlerConfiguration->m_namedPropertyHandler.flags) &
+             static_cast<int>(PropertyHandlerFlags::kHasNoSideEffect));
+
+        if (hasNone) {
+          return TemplatePropertyAttribute::TemplatePropertyAttributeExist;
+        } else if (hasNoSideEffect) {
+          return TemplatePropertyAttribute::TemplatePropertyAttributeEnumerable;
+        } else {
+          LWNODE_UNIMPLEMENT;
+        }
         return TemplatePropertyAttribute::TemplatePropertyAttributeExist;
       }
 
@@ -686,14 +732,20 @@ bool ObjectTemplate::IsImmutableProto() {
   LWNODE_RETURN_FALSE;
 }
 
-void ObjectTemplate::SetImmutableProto() {}
+void ObjectTemplate::SetImmutableProto() {
+  LWNODE_RETURN_VOID;
+}
 
 MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
-  API_ENTER_WITH_CONTEXT(context, MaybeLocal<v8::Object>());
-  auto esContext = lwIsolate->GetCurrentContext()->get();
+  API_ENTER_WITH_CONTEXT(context, MaybeLocal<v8::Object>(), TEMPLATE);
+  auto esContext = VAL(*context)->context()->get();
   auto esObjectTemplate = CVAL(this)->otpl();
 
-  return Utils::NewLocal<Function>(lwIsolate->toV8(),
-                                   esObjectTemplate->instantiate(esContext));
+  auto newObject = esObjectTemplate->instantiate(esContext);
+  if (ObjectRefHelper::getExtraData(newObject)) {
+    auto objectData = ObjectRefHelper::getExtraData(newObject);
+    ObjectRefHelper::setExtraData(newObject, objectData->clone(), true);
+  }
+  return Utils::NewLocal<Object>(lwIsolate->toV8(), newObject);
 }
 }  // namespace v8
index 17fbd043c850de56a10225697c07374f09953bce..6bca1671a656b00407f518a27dd201c2a512a16d 100644 (file)
@@ -38,6 +38,7 @@
 #include "api/isolate.h"
 #include "api/module.h"
 #include "api/object.h"
+#include "api/serializer.h"
 #include "api/utils/string.h"
 
 namespace i = v8::internal;
index 85db92377246fb559e8622faa241160b6bb1adb4..da850067f64030a57b8fc50a51f55dfee26c0bab 100644 (file)
@@ -17,8 +17,9 @@
 #include "context.h"
 #include "base.h"
 #include "es-helper.h"
-#include "escargot_natives.h"
+#include "extra-data.h"
 #include "isolate.h"
+#include "stack-trace.h"
 
 using namespace Escargot;
 
@@ -51,24 +52,51 @@ static bool createGlobals(ContextRef* context) {
 #if defined(HOST_TIZEN)
 // @todo setup device APIs
 #endif
-  evalJavaScript(context,
-                 "stack_frame",
-                 reinterpret_cast<const char*>(stack_frame_raw),
-                 sizeof(stack_frame_raw));
+  // Create captureStackTrace and stackTraceLimit
+  EvalResult r =
+      Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* {
+        auto errorObject = state->context()
+                               ->globalObject()
+                               ->get(state, StringRef::createFromASCII("Error"))
+                               ->asObject();
+
+        errorObject->set(state,
+                         StringRef::createFromASCII("captureStackTrace"),
+                         StackTrace::createCaptureStackTrace(state));
+        errorObject->set(
+            state,
+            StringRef::createFromASCII("stackTraceLimit"),
+            ValueRef::create(
+                20));  // TODO: get number from '--stack-trace-limit' options
+        return ValueRef::createUndefined();
+      });
+  LWNODE_CHECK(r.isSuccessful());
   return true;
 }
 
+// ContextWrap
+
 ContextWrap::ContextWrap(IsolateWrap* isolate) {
   isolate_ = isolate;
+
   context_ = ContextRef::create(isolate->vmInstance());
 
+  callSite_ = new CallSite(context_);
+
+  auto globalObjectData = new GlobalObjectData();
+  globalObjectData->setInternalFieldCount(
+      GlobalObjectData::kInternalFieldCount);
+  globalObjectData->setInternalField(GlobalObjectData::kContextWrapSlot, this);
+  ObjectRefHelper::setExtraData(context_->globalObject(), globalObjectData);
   createGlobals(context_);
+
+  val_ = context_;
+  type_ = Type::Context;
 }
 
 ContextWrap* ContextWrap::New(IsolateWrap* isolate) {
   LWNODE_CHECK_NOT_NULL(isolate);
-  auto context = new ContextWrap(isolate);
-  return context;
+  return new ContextWrap(isolate);
 }
 
 void ContextWrap::Enter() {
index a9b4be0eada103dd7faab2cd4213ca0a1730da5b..81ce21191c0e2b149d04197f8371bf50ba305137 100644 (file)
 #pragma once
 
 #include <EscargotPublic.h>
-#include "utils/gc.h"
+#include "api/handle.h"
 
 namespace EscargotShim {
 
 class IsolateWrap;
-class ValueWrap;
+class CallSite;
 
 typedef GCUnorderedMap<int, void*> EmbedderDataMap;
 
-class ContextWrap : public gc {
+class ContextWrap : public ValueWrap {
  public:
   static ContextWrap* New(IsolateWrap* isolate);
 
@@ -49,6 +49,8 @@ class ContextWrap : public gc {
   Escargot::ValueRef* GetSecurityToken();
   void UseDefaultSecurityToken();
 
+  CallSite* callSite() { return callSite_; }
+
  private:
   EmbedderDataMap* embedder_data_{nullptr};
 
@@ -60,6 +62,8 @@ class ContextWrap : public gc {
   Escargot::ContextRef* context_ = nullptr;
   Escargot::ObjectRef* bindingObject_ = nullptr;
   Escargot::ValueRef* security_token_ = nullptr;
+
+  CallSite* callSite_ = nullptr;
 };
 
 }  // namespace EscargotShim
index 5122b4b6c263cbdedf7e8ff1d45ccd2038c4c108..786169747d339804b6dd19ddcb243819721ee681 100644 (file)
@@ -18,7 +18,6 @@
 #include <iomanip>
 #include <sstream>
 #include "handle.h"
-#include "utils/logger.h"
 #include "utils/misc.h"
 #include "utils/string.h"
 
@@ -37,8 +36,7 @@ Platform* Platform::GetInstance() {
 
 void Platform::Dispose() {
   LWNODE_CALL_TRACE_GC_START();
-  delete s_platform;
-  s_platform = nullptr;
+  // s_platform is freed in Escargot::PlatformBridge
   LWNODE_CALL_TRACE_GC_END();
 }
 
@@ -251,7 +249,7 @@ void GCHeap::printStatus(bool forcePrint) {
     return;
   }
 
-  LWNODE_DLOG_INFO(COLOR_GREEN "----- GCHEAP -----" COLOR_RESET);
+  LWNODE_DLOG_INFO(CLR_GREEN "----- GCHEAP -----" CLR_RESET);
   LWNODE_DLOG_INFO("[STAT]");
   LWNODE_DLOG_INFO("     freed: %zu", stat_.freed);
   LWNODE_DLOG_INFO("    strong: %zu", persistents_.size());
@@ -265,7 +263,7 @@ void GCHeap::printStatus(bool forcePrint) {
                         << std::setw(3) << iter.second.weak << ") ";
                });
 
-  LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET);
+  LWNODE_DLOG_INFO(CLR_GREEN "------------------" CLR_RESET);
   LWNODE_DLOG_INFO("[PHANTOM]");
   printAddress(weakPhantoms_,
                [](std::stringstream& stream, const HeapSegment& iter) {
@@ -275,7 +273,7 @@ void GCHeap::printStatus(bool forcePrint) {
                         << std::setw(3) << iter.second.weak << ") ";
                });
 
-  LWNODE_DLOG_INFO(COLOR_GREEN "------------------" COLOR_RESET);
+  LWNODE_DLOG_INFO(CLR_GREEN "------------------" CLR_RESET);
 }
 
 void GCHeap::postUpdate(void* address) {
@@ -349,7 +347,7 @@ void Engine::initialize() {
   mallopt(M_MMAP_MAX, 1024 * 1024);
 #endif
 
-  Globals::initialize();
+  Globals::initialize(Platform::GetInstance());
   Memory::setGCFrequency(GC_FREE_SPACE_DIVISOR);
   gcHeap_.reset(GCHeap::create());
 
index e41841336996efbdc9b9e9115b9e46f4e2b2459f..bf98eb1a44e9ad00e52c1cd5e2c0e8e07a2a2f1e 100755 (executable)
@@ -27,6 +27,8 @@ using namespace Escargot;
 
 namespace EscargotShim {
 
+// --- ObjectRefHelper ---
+
 ObjectRef* ObjectRefHelper::create(ContextRef* context) {
   EvalResult r =
       Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* {
@@ -63,6 +65,82 @@ EvalResult ObjectRefHelper::setProperty(ContextRef* context,
       value);
 }
 
+ValueRef* ObjectRefHelper::getOwnPropertyAttributes(ExecutionStateRef* state,
+                                                    ObjectRef* object,
+                                                    ValueRef* key) {
+  auto val = object->getOwnPropertyDescriptor(state, key);
+  if (val->isUndefined()) {
+    return ValueRef::createUndefined();
+  }
+
+  int attr = ObjectRef::PresentAttribute::NotPresent;
+
+  bool isWritable = val->asObject()
+                        ->get(state, StringRef::createFromASCII("writable"))
+                        ->asBoolean();
+  bool isEnumerable = val->asObject()
+                          ->get(state, StringRef::createFromASCII("enumerable"))
+                          ->asBoolean();
+  bool isConfigurable =
+      val->asObject()
+          ->get(state, StringRef::createFromASCII("configurable"))
+          ->asBoolean();
+
+  if (isWritable) {
+    attr = attr | ObjectRef::PresentAttribute::WritablePresent;
+  } else {
+    attr = attr | ObjectRef::PresentAttribute::NonWritablePresent;
+  }
+
+  if (isEnumerable) {
+    attr = attr | ObjectRef::PresentAttribute::EnumerablePresent;
+  } else {
+    attr = attr | ObjectRef::PresentAttribute::NonEnumerablePresent;
+  }
+
+  if (isConfigurable) {
+    attr = attr | ObjectRef::PresentAttribute::ConfigurablePresent;
+  } else {
+    attr = attr | ObjectRef::PresentAttribute::NonConfigurablePresent;
+  }
+
+  return ValueRef::create(attr);
+}
+
+EvalResult ObjectRefHelper::getPropertyAttributes(ContextRef* context,
+                                                  ObjectRef* object,
+                                                  ValueRef* key,
+                                                  bool skipPrototype) {
+  LWNODE_DCHECK_NOT_NULL(object);
+  LWNODE_DCHECK_NOT_NULL(key);
+
+  EvalResult r = Evaluator::execute(
+      context,
+      [](ExecutionStateRef* state,
+         ObjectRef* object,
+         ValueRef* key,
+         bool skipPrototype) -> ValueRef* {
+        LWNODE_DCHECK_NOT_NULL(object);
+        LWNODE_DCHECK_NOT_NULL(key);
+
+        ValueRef* attr = ValueRef::createUndefined();
+        for (ObjectRef* o = object; o;
+             o = o->getPrototypeObject(state).value()) {
+          attr = getOwnPropertyAttributes(state, o, key);
+          if (skipPrototype || !attr->isUndefined()) {
+            break;
+          }
+        }
+
+        return attr;
+      },
+      object,
+      key,
+      skipPrototype);
+
+  return r;
+}
+
 EvalResult ObjectRefHelper::getProperty(ContextRef* context,
                                         ObjectRef* object,
                                         ValueRef* key) {
@@ -78,6 +156,20 @@ EvalResult ObjectRefHelper::getProperty(ContextRef* context,
       key);
 }
 
+EvalResult ObjectRefHelper::getOwnProperty(ContextRef* context,
+                                           ObjectRef* object,
+                                           ValueRef* key) {
+  LWNODE_DCHECK_NOT_NULL(object);
+  LWNODE_DCHECK_NOT_NULL(key);
+
+  return Evaluator::execute(
+      context,
+      [](ExecutionStateRef* esState, ObjectRef* object, ValueRef* key)
+          -> ValueRef* { return object->getOwnProperty(esState, key); },
+      object,
+      key);
+}
+
 EvalResult ObjectRefHelper::hasProperty(ContextRef* context,
                                         ObjectRef* object,
                                         ValueRef* key) {
@@ -308,19 +400,14 @@ bool ObjectRefHelper::hasExtraData(ObjectRef* object) {
   return false;
 }
 
-void ObjectRefHelper::setExtraData(
-    ObjectRef* object,
-    ObjectData* data,
-    Memory::GCAllocatedMemoryFinalizer callback) {
-  if (object->extraData()) {
+void ObjectRefHelper::setExtraData(ObjectRef* object,
+                                   ObjectData* data,
+                                   bool isForceReplace) {
+  if (isForceReplace == false && object->extraData()) {
     LWNODE_DLOG_WARN("extra data already exists. it will be removed.");
   }
 
   object->setExtraData(data);
-
-  if (callback) {
-    MemoryUtil::gcRegisterFinalizer(object, callback);
-  }
 }
 
 ObjectData* ObjectRefHelper::getExtraData(ObjectRef* object) {
@@ -391,6 +478,37 @@ static std::string getCodeLine(const std::string& codeString, int errorLine) {
   return result;
 }
 
+std::string EvalResultHelper::getCallStackString(
+    const GCManagedVector<Evaluator::StackTraceData>& traceData,
+    size_t maxStackSize) {
+  std::ostringstream oss;
+  const std::string separator = "  ";
+  size_t maxPrintStackSize = std::min((int)maxStackSize, (int)traceData.size());
+
+  oss << "Call Stack:" << std::endl;
+  for (size_t i = 0; i < maxPrintStackSize; ++i) {
+    const auto& iter = traceData[i];
+    const auto& resourceName = iter.src->toStdUTF8String();
+    const auto& codeString = iter.sourceCode->toStdUTF8String();
+    const int errorLine = iter.loc.line;
+    const int errorColumn = iter.loc.column;
+
+    auto sourceOnStack = getCodeLine(codeString, errorLine);
+
+    // Trim left spaces
+    auto pos = sourceOnStack.find_first_not_of(' ');
+    auto errorCodeLine =
+        sourceOnStack.substr(pos != std::string::npos ? pos : 0);
+
+    oss << separator << i << ": " << (errorCodeLine == "" ? "?" : errorCodeLine)
+        << " ";
+    oss << "(" << (resourceName == "" ? "?" : resourceName) << ":" << errorLine
+        << ":" << errorColumn << ")" << std::endl;
+  }
+
+  return oss.str();
+}
+
 std::string EvalResultHelper::getErrorString(
     ContextRef* context, const Evaluator::EvaluatorResult& result) {
   const auto& traceData = result.stackTraceData;
@@ -434,28 +552,7 @@ std::string EvalResultHelper::getErrorString(
       }
     }
 
-    size_t maxPrintStackSize = std::min(5, (int)traceData.size());
-
-    oss << "Call Stack:" << std::endl;
-    for (size_t i = 0; i < maxPrintStackSize; ++i) {
-      const auto& iter = traceData[i];
-      const auto& resourceName = iter.src->toStdUTF8String();
-      const auto& codeString = iter.sourceCode->toStdUTF8String();
-      const int errorLine = iter.loc.line;
-      const int errorColumn = iter.loc.column;
-
-      auto sourceOnStack = getCodeLine(codeString, errorLine);
-
-      // Trim left spaces
-      auto pos = sourceOnStack.find_first_not_of(' ');
-      auto errorCodeLine =
-          sourceOnStack.substr(pos != std::string::npos ? pos : 0);
-
-      oss << separator << i << ": "
-          << (errorCodeLine == "" ? "?" : errorCodeLine) << " ";
-      oss << "(" << (resourceName == "" ? "?" : resourceName) << ":"
-          << errorLine << ":" << errorColumn << ")" << std::endl;
-    }
+    oss << getCallStackString(traceData);
   }
 
   return oss.str();
@@ -475,60 +572,148 @@ Evaluator::EvaluatorResult EvalResultHelper::compileRun(ContextRef* context,
         context, compileResult.parseErrorCode, compileResult.parseErrorMessage);
 
     LWNODE_LOG_ERROR(
-        "%s", result.resultOrErrorToString(context)->toStdUTF8String().c_str());
+        "Compile: %s",
+        result.resultOrErrorToString(context)->toStdUTF8String().c_str());
     return result;
   }
 
-  return Evaluator::execute(
+  auto r = Evaluator::execute(
       context,
       [](ExecutionStateRef* state, ScriptRef* script) -> ValueRef* {
         return script->execute(state);
       },
       compileResult.script.get());
+
+  if (r.isSuccessful() == false) {
+    LWNODE_DLOG_RAW("Execute:\n  %s (%s:%d)\n%s",
+                    TRACE_ARGS2,
+                    EvalResultHelper::getErrorString(context, r).c_str());
+  }
+  return r;
 }
 
-void EvalResultHelper::attachBuiltinPrint(ContextRef* context) {
+void EvalResultHelper::attachBuiltinPrint(ContextRef* context,
+                                          ObjectRef* target) {
   static auto builtinPrint = [](ExecutionStateRef* state,
                                 ValueRef* thisValue,
                                 size_t argc,
                                 ValueRef** argv,
                                 bool isConstructCall) -> ValueRef* {
     if (argc > 0) {
-      if (argv[0]->isSymbol()) {
-        puts(argv[0]
-                 ->asSymbol()
-                 ->symbolDescriptiveString()
-                 ->toStdUTF8String()
-                 .c_str());
-      } else {
-        puts(argv[0]->toString(state)->toStdUTF8String().c_str());
+      std::stringstream ss;
+
+      for (size_t i = 0; i < argc; ++i) {
+        if (argv[i]->isSymbol()) {
+          ss << argv[i]
+                    ->asSymbol()
+                    ->symbolDescriptiveString()
+                    ->toStdUTF8String();
+        } else {
+          ss << argv[i]
+                    ->toStringWithoutException(state->context())
+                    ->toStdUTF8String();
+        }
+        ss << " ";
       }
-    } else {
-      puts("undefined");
+
+      LWNODE_DLOG_RAW("%s", ss.str().c_str());
     }
     return ValueRef::createUndefined();
   };
 
-  Evaluator::execute(context, [](ExecutionStateRef* state) -> ValueRef* {
-    ContextRef* context = state->context();
+  static auto builtinPrintAddress = [](ExecutionStateRef* state,
+                                       ValueRef* thisValue,
+                                       size_t argc,
+                                       ValueRef** argv,
+                                       bool isConstructCall) -> ValueRef* {
+    if (argc > 0) {
+      std::stringstream ss;
+
+      for (size_t i = 0; i < argc; ++i) {
+        if (argv[i]->isString()) {
+          ss << argv[i]
+                    ->toStringWithoutException(state->context())
+                    ->toStdUTF8String();
+        } else {
+          ss << CLR_DIM << "(" << argv[i] << ")" << CLR_RESET;
+        }
+        ss << " ";
+      }
+
+      LWNODE_DLOG_RAW("%s", ss.str().c_str());
+    }
+    return ValueRef::createUndefined();
+  };
 
-    FunctionObjectRef::NativeFunctionInfo info(
-        AtomicStringRef::create(context, "print"),
-        builtinPrint,
-        1,
-        true,
-        false);
+  static auto builtinPrintCallStack = [](ExecutionStateRef* state,
+                                         ValueRef* thisValue,
+                                         size_t argc,
+                                         ValueRef** argv,
+                                         bool isConstructCall) -> ValueRef* {
+    size_t maxStackSize = 5;
 
-    context->globalObject()->defineDataProperty(
-        state,
-        StringRef::createFromASCII("print"),
-        FunctionObjectRef::create(state, info),
-        true,
-        true,
-        true);
+    if (argc == 1 && argv[0]->isUInt32()) {
+      maxStackSize = argv[0]->toUint32(state);
+    }
+
+    LWNODE_DLOG_RAW(
+        "%s",
+        getCallStackString(state->computeStackTraceData(), maxStackSize)
+            .c_str());
 
     return ValueRef::createUndefined();
-  });
+  };
+
+  Evaluator::execute(
+      context,
+      [](ExecutionStateRef* state, ObjectRef* target) -> ValueRef* {
+        auto esPrint =
+            FunctionObjectRef::create(state,
+                                      FunctionObjectRef::NativeFunctionInfo(
+                                          AtomicStringRef::emptyAtomicString(),
+                                          builtinPrint,
+                                          1,
+                                          true,
+                                          false));
+
+        esPrint->defineDataProperty(
+            state,
+            StringRef::createFromASCII("ptr"),
+            FunctionObjectRef::create(state,
+                                      FunctionObjectRef::NativeFunctionInfo(
+                                          AtomicStringRef::emptyAtomicString(),
+                                          builtinPrintAddress,
+                                          1,
+                                          true,
+                                          false)),
+            true,
+            true,
+            true);
+
+        esPrint->defineDataProperty(
+            state,
+            StringRef::createFromASCII("stack"),
+            FunctionObjectRef::create(state,
+                                      FunctionObjectRef::NativeFunctionInfo(
+                                          AtomicStringRef::emptyAtomicString(),
+                                          builtinPrintCallStack,
+                                          1,
+                                          true,
+                                          false)),
+            true,
+            true,
+            true);
+
+        target->defineDataProperty(state,
+                                   StringRef::createFromASCII("print"),
+                                   esPrint,
+                                   true,
+                                   true,
+                                   true);
+
+        return ValueRef::createUndefined();
+      },
+      target);
 }
 
 ObjectData* ObjectRefHelper::createExtraDataIfNotExist(ObjectRef* object) {
@@ -560,6 +745,7 @@ void ObjectRefHelper::setInternalField(ObjectRef* object,
                                        InternalField* lwValue) {
   auto data = getExtraData(object);
   LWNODE_CHECK_NOT_NULL(data);
+
   data->setInternalField(idx, lwValue);
 }
 
@@ -567,7 +753,12 @@ InternalField* ObjectRefHelper::getInternalField(ObjectRef* object, int idx) {
   auto data = getExtraData(object);
   LWNODE_CHECK_NOT_NULL(data);
 
-  return reinterpret_cast<InternalField*>(data->internalField(idx));
+  auto field = reinterpret_cast<InternalField*>(data->internalField(idx));
+  if (!field) {
+    return IsolateWrap::GetCurrent()->undefined_value();
+  }
+
+  return field;
 }
 
 void ObjectRefHelper::setInternalPointer(ObjectRef* object,
@@ -580,12 +771,16 @@ void ObjectRefHelper::setInternalPointer(ObjectRef* object,
 }
 
 void* ObjectRefHelper::getInternalPointer(ObjectRef* object, int idx) {
-  auto data = getExtraData(object);
-  LWNODE_CHECK_NOT_NULL(data);
+  auto extraData = getExtraData(object);
+  LWNODE_CHECK_NOT_NULL(extraData);
+
+  auto data = extraData->internalField(idx);
 
-  return data->internalField(idx);
+  return data;
 }
 
+// --- ObjectTemplateRefHelper ---
+
 void ObjectTemplateRefHelper::setInstanceExtraData(ObjectTemplateRef* otpl,
                                                    ObjectData* data) {
   LWNODE_CHECK_NOT_NULL(data);
@@ -627,8 +822,11 @@ int ObjectTemplateRefHelper::getInternalFieldCount(ObjectTemplateRef* otpl) {
   return data->internalFieldCount();
 }
 
+// --- FunctionTemplateRefHelper ---
+
 void FunctionTemplateRefHelper::setInstanceExtraData(FunctionTemplateRef* ftpl,
                                                      FunctionData* data) {
+  LWNODE_CALL_TRACE_ID(OBJDATA, "es: %p data: %p", ftpl, data);
   LWNODE_CHECK_NOT_NULL(data);
   LWNODE_CHECK_NULL(ftpl->instanceExtraData());
 
@@ -638,9 +836,12 @@ void FunctionTemplateRefHelper::setInstanceExtraData(FunctionTemplateRef* ftpl,
 FunctionData* FunctionTemplateRefHelper::getInstanceExtraData(
     FunctionTemplateRef* ftpl) {
   auto data = ftpl->instanceExtraData();
+  LWNODE_CALL_TRACE_ID(OBJDATA, "es: %p data: %p", ftpl, data);
   return reinterpret_cast<FunctionData*>(data);
 }
 
+// --- ExceptionHelper ---
+
 ValueWrap* ExceptionHelper::wrapException(ValueRef* exception) {
   return ValueWrap::createValue(exception);
 }
@@ -666,4 +867,25 @@ ErrorObjectRef* ExceptionHelper::createErrorObject(ContextRef* context,
   return r.result->asErrorObject();
 }
 
+// --- StringRefHelper ---
+
+bool StringRefHelper::isAsciiString(StringRef* str) {
+  auto bufferData = str->stringBufferAccessData();
+
+  if (!bufferData.has8BitContent) {
+    return false;
+  }
+
+  bool isAscii = true;
+  for (size_t i = 0; i < bufferData.length; i++) {
+    char16_t c = bufferData.charAt(i);
+    if (c > 127) {  // including all 7 bit code
+      isAscii = false;
+      break;
+    }
+  }
+
+  return isAscii;
+}
+
 }  // namespace EscargotShim
index 26b476511adc17cb2bf3667946b800808c93de0b..e3bddf3557de8464885a212f6befa12b8e464235 100755 (executable)
@@ -51,6 +51,15 @@ class ObjectRefHelper {
                                 ValueRef* key,
                                 ValueRef* value);
 
+  static EvalResult getOwnProperty(ContextRef* context,
+                                   ObjectRef* object,
+                                   ValueRef* key);
+
+  static EvalResult getPropertyAttributes(ContextRef* context,
+                                          ObjectRef* object,
+                                          ValueRef* key,
+                                          bool skipPrototype = false);
+
   static EvalResult hasProperty(ContextRef* context,
                                 ObjectRef* object,
                                 ValueRef* key);
@@ -90,13 +99,11 @@ class ObjectRefHelper {
       ValueRef* propertyName,
       const ObjectRef::AccessorPropertyDescriptor& descriptor);
 
-  static void setExtraData(
-      ObjectRef* object,
-      ObjectData* data,
-      Memory::GCAllocatedMemoryFinalizer callback = nullptr);
+  static void setExtraData(ObjectRef* object,
+                           ObjectData* data,
+                           bool isForceReplace = false);
   static bool hasExtraData(ObjectRef* object);
   static ObjectData* getExtraData(ObjectRef* object);
-  static ObjectData* createExtraDataIfNotExist(ObjectRef* object);
 
   static void setInternalFieldCount(ObjectRef* object, int size);
   static int getInternalFieldCount(ObjectRef* object);
@@ -112,15 +119,22 @@ class ObjectRefHelper {
   static StringRef* getConstructorName(ContextRef* context, ObjectRef* object);
 
  private:
+  static ObjectData* createExtraDataIfNotExist(ObjectRef* object);
+
+  static ValueRef* getOwnPropertyAttributes(ExecutionStateRef* state,
+                                            ObjectRef* object,
+                                            ValueRef* key);
 };
 
 class ObjectTemplateRefHelper {
  public:
   static void setInstanceExtraData(ObjectTemplateRef* otpl, ObjectData* data);
   static ObjectData* getInstanceExtraData(ObjectTemplateRef* otpl);
-  static ObjectData* createInstanceExtraDataIfNotExist(ObjectTemplateRef* otpl);
   static void setInternalFieldCount(ObjectTemplateRef* otpl, int size);
   static int getInternalFieldCount(ObjectTemplateRef* otpl);
+
+ private:
+  static ObjectData* createInstanceExtraDataIfNotExist(ObjectTemplateRef* otpl);
 };
 
 class FunctionTemplateRefHelper {
@@ -197,12 +211,15 @@ class ArrayBufferHelper {
 
 class EvalResultHelper {
  public:
-  static void attachBuiltinPrint(ContextRef* context);
+  static void attachBuiltinPrint(ContextRef* context, ObjectRef* target);
   static Evaluator::EvaluatorResult compileRun(ContextRef* context,
                                                const char* source,
                                                bool isModule = false);
   static std::string getErrorString(
       ContextRef* context, const Evaluator::EvaluatorResult& eval_result);
+  static std::string getCallStackString(
+      const GCManagedVector<Evaluator::StackTraceData>& traceData,
+      size_t maxStackSize = 5);
 };
 
 class ExceptionHelper {
@@ -220,6 +237,8 @@ class StringRefHelper {
   static bool equalsWithASCIIString(StringRef* esString, const char (&str)[N]) {
     return esString->equalsWithASCIIString(str, N - 1);
   }
+
+  static bool isAsciiString(StringRef* str);
 };
 
 }  // namespace EscargotShim
index d581650b0532b065bbaa732ce9a48ad4a04e74a1..474b3bbc96bb7798996188b5f954a0694b27e91e 100644 (file)
@@ -26,19 +26,50 @@ ObjectRef::PresentAttribute V8Helper::toPresentAttribute(
   if (attributes & v8::ReadOnly) {
     presentAttributes = static_cast<ObjectRef::PresentAttribute>(
         presentAttributes | ObjectRef::PresentAttribute::NonWritablePresent);
+  } else {
+    presentAttributes = static_cast<ObjectRef::PresentAttribute>(
+        presentAttributes | ObjectRef::PresentAttribute::WritablePresent);
   }
 
   if (attributes & v8::DontEnum) {
     presentAttributes = static_cast<ObjectRef::PresentAttribute>(
         presentAttributes | ObjectRef::PresentAttribute::NonEnumerablePresent);
+  } else {
+    presentAttributes = static_cast<ObjectRef::PresentAttribute>(
+        presentAttributes | ObjectRef::PresentAttribute::EnumerablePresent);
   }
 
   if (attributes & v8::DontDelete) {
     presentAttributes = static_cast<ObjectRef::PresentAttribute>(
         presentAttributes |
         ObjectRef::PresentAttribute::NonConfigurablePresent);
+  } else {
+    presentAttributes = static_cast<ObjectRef::PresentAttribute>(
+        presentAttributes | ObjectRef::PresentAttribute::ConfigurablePresent);
   }
 
   return presentAttributes;
 }
+
+v8::PropertyAttribute V8Helper::toPropertyAttribute(
+    ObjectRef::PresentAttribute attributes) {
+  int propertyAttributes = v8::PropertyAttribute::None;
+
+  if (attributes & ObjectRef::PresentAttribute::NonWritablePresent) {
+    propertyAttributes =
+        propertyAttributes | ObjectRef::PresentAttribute::NonWritablePresent;
+  }
+
+  if (attributes & ObjectRef::PresentAttribute::NonEnumerablePresent) {
+    propertyAttributes =
+        propertyAttributes | ObjectRef::PresentAttribute::NonEnumerablePresent;
+  }
+
+  if (attributes & ObjectRef::PresentAttribute::NonConfigurablePresent) {
+    propertyAttributes = propertyAttributes |
+                         ObjectRef::PresentAttribute::NonConfigurablePresent;
+  }
+
+  return static_cast<v8::PropertyAttribute>(propertyAttributes);
+}
 }  // namespace EscargotShim
index 6c430c25749c73cfba500e19549632c35ed850e7..4d09bcbff82d8155776e5e1e55ca09cc8254834d 100644 (file)
@@ -27,6 +27,8 @@ class V8Helper {
  public:
   static ObjectRef::PresentAttribute toPresentAttribute(
       v8::PropertyAttribute attributes);
+  static v8::PropertyAttribute toPropertyAttribute(
+      ObjectRef::PresentAttribute attributes);
 };
 
 }  // namespace EscargotShim
index f1547e586e621bb2c2b952eef45402390e061377..d9bd2711b6bfd37b68ddb0858692a36e55c649c9 100644 (file)
@@ -30,6 +30,22 @@ static inline bool checkOutofBounds(ObjectData* data, int idx) {
   return idx >= data->internalFieldCount() || idx < 0;
 }
 
+static std::string toObjectDataString(const ObjectData* data,
+                                      int index,
+                                      const void* field) {
+  std::ostringstream oss;
+
+  oss << " fields (" << data << ")";
+  oss << " [" << index << "]";
+
+  if (field && CVAL(field)->isValid()) {
+    oss << " " << CVAL(field)->getHandleInfoString();
+  } else {
+    oss << " " << field;
+  }
+  return oss.str();
+}
+
 int ObjectData::internalFieldCount() {
   if (m_internalFields == nullptr) {
     return 0;
@@ -38,14 +54,17 @@ int ObjectData::internalFieldCount() {
 }
 
 void ObjectData::setInternalFieldCount(int size) {
+  LWNODE_CALL_TRACE_ID(OBJDATA, "%d", size);
+
   // TODO: throw internal error
   if (size <= 0) {
     LWNODE_DLOG_ERROR("InternalField: The size is negative");
     return;
   }
+
   m_internalFields = new GCContainer<void*>(size);
   for (int i = 0; i < size; i++) {
-    m_internalFields->set(i, IsolateWrap::GetCurrent()->undefined());
+    setInternalField(i, nullptr);
   }
 }
 
@@ -56,6 +75,10 @@ void ObjectData::setInternalField(int idx, void* lwValue) {
     LWNODE_DLOG_ERROR("InternalField: Internal field out of bounds");
     return;
   }
+
+  LWNODE_CALL_TRACE_ID(
+      OBJDATA, "%s", toObjectDataString(this, idx, lwValue).c_str());
+
   m_internalFields->set(idx, lwValue);
 }
 
@@ -66,7 +89,40 @@ void* ObjectData::internalField(int idx) {
     LWNODE_DLOG_ERROR("InternalField: Internal field out of bounds");
     return nullptr;
   }
-  return m_internalFields->get(idx);
+
+  void* field = m_internalFields->get(idx);
+  if (field) {
+    LWNODE_CALL_TRACE_ID(
+        OBJDATA, "%s", toObjectDataString(this, idx, field).c_str());
+  }
+
+  return field;
+}
+
+ObjectData* ObjectData::clone() {
+  auto newData = new ObjectData();
+
+  LWNODE_CALL_TRACE_ID(OBJDATA, "%p clone: %p", this, newData);
+
+  // copy internalField
+  auto count = internalFieldCount();
+  if (count > 0) {
+    newData->setInternalFieldCount(count);
+  }
+  for (int i = 0; i < count; i++) {
+    LWNODE_DCHECK(internalField(i) == nullptr);
+    newData->setInternalField(i, internalField(i));
+  }
+
+  return newData;
+}
+
+void ObjectData::setInstanceTemplate(Escargot::FunctionTemplateRef* tpl) {
+  instanceTemplate_ = tpl;
+}
+
+Escargot::FunctionTemplateRef* ObjectData::instanceTemplate() {
+  return instanceTemplate_;
 }
 
 bool FunctionData::checkSignature(Escargot::ExecutionStateRef* state,
@@ -89,7 +145,30 @@ bool FunctionData::checkSignature(Escargot::ExecutionStateRef* state,
   return r.result->asBoolean();
 }
 
-GCVector<ExceptionObjectData::StackTraceData*>* ExceptionObjectData::stackTrace(
+static bool isValidStackFrame(const Evaluator::StackTraceData& traceData) {
+  const int errorLine = traceData.loc.line;
+  const int errorColumn = traceData.loc.column;
+  // simple filter for { [native function] } :-1:-1)
+  return (errorLine > 0 && errorColumn > 0);
+}
+
+ExceptionObjectData::ExceptionObjectData(
+    GCManagedVector<Escargot::Evaluator::StackTraceData>& stackTraceData,
+    bool isThisExceptionUndefined)
+    : isThisExceptionUndefined_(isThisExceptionUndefined) {
+  constexpr const char* kNativeFunction = "[native function]";
+
+  for (size_t i = 0; i < stackTraceData.size(); i++) {
+    const auto& traceData = stackTraceData[i];
+    if (isValidStackFrame(traceData) == false) {
+      LWNODE_DLOG_INFO("filtered: stack frame #%zu", i);
+      continue;
+    }
+    stackTraces_.push_back(new StackTraceData(traceData));
+  }
+}
+
+GCVector<StackTraceData*>* ExceptionObjectData::stackTrace(
     ObjectRef* exceptionObject) {
   auto exceptionObjectData = static_cast<ExceptionObjectData*>(
       ObjectRefHelper::getExtraData(exceptionObject));
index 2c73db9972f001fcbf4b8f51b04a7f9b917e2e0c..e93482a14bd4115be942980b216e40fcafb4a994 100644 (file)
@@ -23,6 +23,9 @@
 
 namespace EscargotShim {
 class ExternalObjectData;
+class GlobalObjectData;
+class ExceptionObjectData;
+class StackTraceData;
 class ValueWrap;
 class BackingStoreWrap;
 
@@ -35,9 +38,28 @@ class ObjectData : public gc {
     return reinterpret_cast<ExternalObjectData*>(this);
   }
 
+  GlobalObjectData* asGlobalObjectData() {
+    LWNODE_CHECK(isGlobalObjectData());
+    return reinterpret_cast<GlobalObjectData*>(this);
+  }
+
+  ExceptionObjectData* asExceptionObjectData() {
+    LWNODE_CHECK(isExceptionObjectData());
+    return reinterpret_cast<ExceptionObjectData*>(this);
+  }
+
+  StackTraceData* asStackTraceData() {
+    LWNODE_CHECK(isStackTraceData());
+    return reinterpret_cast<StackTraceData*>(this);
+  }
+
   virtual bool isFunctionData() const { return false; }
   virtual bool isExternalObjectData() const { return false; }
   virtual bool isExceptionObjectData() const { return false; }
+  virtual bool isStackTraceData() const { return false; }
+  virtual bool isGlobalObjectData() const { return false; }
+
+  ObjectData* clone();
 
   // InternalFields
   int internalFieldCount();
@@ -45,8 +67,13 @@ class ObjectData : public gc {
   void setInternalField(int idx, void* lwValue);
   void* internalField(int idx);
 
+  // Template
+  void setInstanceTemplate(Escargot::FunctionTemplateRef* tpl);
+  Escargot::FunctionTemplateRef* instanceTemplate();
+
  private:
   GCContainer<void*>* m_internalFields{nullptr};
+  Escargot::FunctionTemplateRef* instanceTemplate_{nullptr};
 };
 
 class FunctionData : public ObjectData {
@@ -87,37 +114,63 @@ class FunctionData : public ObjectData {
 
 class ExternalObjectData : public ObjectData {
  public:
+  enum InternalFields {
+    kValueSlot,
+    kInternalFieldCount,
+  };
   bool isExternalObjectData() const override { return true; }
 };
 
-class ExceptionObjectData : public ObjectData {
+// TODO: check to make sure StackTraceData inherit ObjectData.
+class StackTraceData : public ObjectData {
  public:
-  struct StackTraceData : public gc {
-   public:
-    StackTraceData(Escargot::Evaluator::StackTraceData& data)
-        : src(data.src),
-          sourceCode(data.sourceCode),
-          loc(data.loc),
-          functionName(data.functionName),
-          isConstructor(data.isConstructor),
-          isAssociatedWithJavaScriptCode(data.isAssociatedWithJavaScriptCode),
-          isEval(data.isEval) {}
-
-    StringRef* src{nullptr};
-    StringRef* sourceCode{nullptr};
-    Escargot::Evaluator::LOC loc{0, 0, 0};
-    StringRef* functionName{nullptr};
-    bool isFunction{false};
-    bool isConstructor{false};
-    bool isAssociatedWithJavaScriptCode{false};
-    bool isEval{false};
-  };
+  StackTraceData(const Escargot::Evaluator::StackTraceData& data)
+      : src_(data.src),
+        sourceCode_(data.sourceCode),
+        loc_(data.loc),
+        functionName_(data.functionName),
+        isConstructor_(data.isConstructor),
+        isAssociatedWithJavaScriptCode_(data.isAssociatedWithJavaScriptCode),
+        isEval_(data.isEval) {}
+
+  bool isStackTraceData() const override { return true; }
+
+  StringRef* src() const { return src_; }
+  StringRef* sourceCode() const { return sourceCode_; }
+  Escargot::Evaluator::LOC loc() const { return loc_; }
+  StringRef* functionName() const { return functionName_; }
+  bool isFunction() const { return isFunction_; }
+  bool isConstructor() const { return isConstructor_; }
+  bool isAssociatedWithJavaScriptCode() const {
+    return isAssociatedWithJavaScriptCode_;
+  }
+  bool isEval() const { return isEval_; }
 
+ private:
+  StringRef* src_{nullptr};
+  StringRef* sourceCode_{nullptr};
+  Escargot::Evaluator::LOC loc_{0, 0, 0};
+  StringRef* functionName_{nullptr};
+  bool isFunction_{false};
+  bool isConstructor_{false};
+  bool isAssociatedWithJavaScriptCode_{false};
+  bool isEval_{false};
+};
+
+class ExceptionObjectData : public ObjectData {
+ public:
  public:
   ExceptionObjectData(
-      GCManagedVector<Escargot::Evaluator::StackTraceData>& stackTraceData) {
-    for (size_t i = 0; i < stackTraceData.size(); i++) {
-      stackTraces_.push_back(new StackTraceData(stackTraceData[i]));
+      GCManagedVector<Escargot::Evaluator::StackTraceData>& stackTraceData,
+      bool isThisExceptionUndefined = false);
+
+  ExceptionObjectData(GCVector<StackTraceData*>* stackTrace,
+                      bool isThisExceptionUndefined = false)
+      : isThisExceptionUndefined_(isThisExceptionUndefined) {
+    {
+      for (const auto& iter : *stackTrace) {
+        stackTraces_.push_back(iter);
+      }
     }
   }
 
@@ -128,6 +181,16 @@ class ExceptionObjectData : public ObjectData {
 
  private:
   GCVector<StackTraceData*> stackTraces_;
+  bool isThisExceptionUndefined_{false};
+};
+
+class GlobalObjectData : public ObjectData {
+ public:
+  enum InternalFields {
+    kContextWrapSlot,
+    kInternalFieldCount,
+  };
+  bool isGlobalObjectData() const override { return true; }
 };
 
 }  // namespace EscargotShim
index b459f5b5e7bddad47db46ebdcf2f5b67b3fa564c..739ed238d6d459fe5a4e0e76169a065670af0f16 100644 (file)
@@ -45,7 +45,7 @@ FunctionCallbackInfoWrap::FunctionCallbackInfoWrap(
   m_implicitArgs[T::kDataIndex] = data;
   m_implicitArgs[T::kNewTargetIndex] =
       newTarget.hasValue() ? ValueWrap::createValue(newTarget.get())
-                           : lwIsolate->undefined();
+                           : lwIsolate->undefined_value();
 }
 
 HandleWrap** FunctionCallbackInfoWrap::toWrapperArgs(ValueRef* thisValue,
@@ -68,8 +68,9 @@ HandleWrap** FunctionCallbackInfoWrap::toWrapperArgs(ValueRef* thisValue,
       string1 // the beginning of the arguments array
   */
 
-  m_args = reinterpret_cast<HandleWrap**>(
-      Escargot::Memory::gcMalloc(sizeof(HandleWrap*) * (argc + 1)));
+  m_args =
+      reinterpret_cast<HandleWrap**>(Escargot::Memory::gcMallocUncollectable(
+          sizeof(HandleWrap*) * (argc + 1)));
 
 #ifdef V8_REVERSE_JSARGS
 #error "Not implement V8_REVERSE_JSARGS"
@@ -109,7 +110,7 @@ PropertyCallbackInfoWrap<T>::PropertyCallbackInfoWrap(v8::Isolate* isolate,
           reinterpret_cast<v8::internal::Address*>(m_implicitArgs)) {
   auto lwIsolate = IsolateWrap::fromV8(isolate);
   // m_implicitArgs[F::kShouldThrowOnErrorIndex]; // TODO
-  m_implicitArgs[F::kHolderIndex] = lwIsolate->hole();
+  m_implicitArgs[F::kHolderIndex] = ValueWrap::createValue(holder);
   m_implicitArgs[F::kIsolateIndex] = reinterpret_cast<HandleWrap*>(isolate);
   // m_implicitArgs[F::kReturnValueDefaultValueIndex]; // TODO
   m_implicitArgs[F::kReturnValueIndex] = lwIsolate->defaultReturnValue();
index 4b06dd430737d6bb03a134dd7416567343d5e8a6..96870292a85a912c09035b4ba5990fc518af547e 100644 (file)
@@ -40,7 +40,7 @@ class FunctionCallbackInfoWrap : public v8::FunctionCallbackInfo<v8::Value> {
   HandleWrap** toWrapperArgs(ValueRef* thisValue, int argc, ValueRef** argv);
 
  private:
-  HandleWrap** m_args{nullptr};
+  HandleWrap** m_args;
   HandleWrap* m_implicitArgs[T::kArgsLength];
 };
 
index 93709e9c8524329e40f05c45dc44574362151817..3580aca52cb39952e387a11f3bb43216cbf06ff2 100644 (file)
@@ -41,7 +41,7 @@ uint8_t HandleWrap::location() const {
 }
 
 bool HandleWrap::isValid() const {
-  return (type_ > Type::NotPresent && type_ < Type::EndOfType);
+  return (type_ >= Type::JsValue && type_ < Type::EndOfType);
 }
 
 bool HandleWrap::isStrongOrWeak() const {
@@ -73,11 +73,13 @@ HandleWrap* HandleWrap::as(void* address) {
   return p;
 }
 
-std::string HandleWrap::getHandleInfoString() {
+std::string HandleWrap::getHandleInfoString() const {
   std::stringstream ss;
-  ss << "(addr: " << this << " es: " << val_
-     << " loc: " << std::to_string(location_)
-     << " type: " << std::to_string(type_) << ")";
+  ss << "(addr: " << this << " es: " << val_;
+  if (location_ != Location::Local) {
+    ss << " loc: " << std::to_string(location_);
+  }
+  ss << " type: " << std::to_string(type_) << ")";
   return ss.str();
 }
 
@@ -117,12 +119,14 @@ ValueRef* ValueWrap::value() const {
 }
 
 ValueWrap* ValueWrap::createContext(ContextWrap* lwContext) {
-  return new ValueWrap(lwContext, Type::Context);
+  LWNODE_CHECK(lwContext->type_ == Type::Context);
+  LWNODE_CHECK_NOT_NULL(lwContext->val_);
+  return lwContext;
 };
 
 ContextWrap* ValueWrap::context() const {
   LWNODE_CHECK(type_ == Type::Context);
-  return reinterpret_cast<ContextWrap*>(val_);
+  return reinterpret_cast<ContextWrap*>(const_cast<ValueWrap*>(this));
 }
 
 ValueWrap* ValueWrap::createScript(ScriptRef* esScript) {
index 533c9548c012f1b19857a8b823a56f280f542c08..060d3525c91ddda59c65b2f60f6f75a433aa9035 100644 (file)
@@ -59,7 +59,7 @@ class HandleWrap : public gc {
   bool isStrongOrWeak() const;
   uint8_t location() const;
   HandleWrap* clone(Location location = Local);
-  std::string getHandleInfoString();
+  std::string getHandleInfoString() const;
   static HandleWrap* as(void* address);
 
  protected:
index 8ed4e4d7b4c58bf33516a4b7ba237d97039dbb5b..f7f30d1b63c484e242037529fcb6b5f4250577a6 100755 (executable)
@@ -26,6 +26,8 @@
 namespace v8 {
 namespace internal {
 
+using namespace EscargotShim;
+
 // 'exception_' is of type ValueWrap*. Ref: api-exception.cc
 void Isolate::SetTerminationOnExternalTryCatch() {
   LWNODE_CALL_TRACE_ID(TRYCATCH, "try_catch_handler_: %p", try_catch_handler_);
@@ -54,6 +56,8 @@ void Isolate::ScheduleThrow(Escargot::ValueRef* value) {
   // using v8:tryCatch, etc. In this case, we should not do any exception
   // handling.
 
+  set_scheduled_exception(value);
+
   // Note: No stack data exist
   GCManagedVector<Escargot::Evaluator::StackTraceData> stackTraceData;
   SetPendingExceptionAndMessage(value, stackTraceData);
@@ -90,17 +94,21 @@ bool Isolate::has_scheduled_exception() {
   return !isHole(scheduled_exception_);
 }
 
+void Isolate::set_scheduled_exception(Escargot::ValueRef* exception_obj) {
+  scheduled_exception_ = exception_obj;
+}
+
 void Isolate::clear_scheduled_exception() {
   LWNODE_CALL_TRACE_ID(TRYCATCH);
   scheduled_exception_ = hole()->value();
 }
 
-Escargot::ObjectRef* Isolate::pending_exception() {
+Escargot::ValueRef* Isolate::pending_exception() {
   LWNODE_CHECK(has_pending_exception());
   return pending_exception_;
 }
 
-void Isolate::set_pending_exception(Escargot::ObjectRef* exception_obj) {
+void Isolate::set_pending_exception(Escargot::ValueRef* exception_obj) {
   LWNODE_CALL_TRACE_ID(TRYCATCH);
   LWNODE_CHECK_NOT_NULL(exception_obj);
   pending_exception_ = exception_obj;
@@ -168,10 +176,12 @@ void Isolate::ReportPendingMessages() {
   if (should_report_exception) {
     v8::HandleScope scope(EscargotShim::IsolateWrap::toV8(this));
 
-    v8::Local<v8::Message> message;
     v8::Local<v8::Value> exception = v8::Utils::NewLocal<v8::Value>(
         EscargotShim::IsolateWrap::toV8(this), pending_exception_);
 
+    v8::Local<v8::Message> message = v8::Exception::CreateMessage(
+        EscargotShim::IsolateWrap::toV8(this), exception);
+
     if (message_callback_ != nullptr) {
       message_callback_(message, exception);
     }
@@ -214,6 +224,19 @@ IsolateWrap::IsolateWrap() {
   Memory::gcRegisterFinalizer(this, [](void* self) {
     reinterpret_cast<IsolateWrap*>(self)->~IsolateWrap();
   });
+
+  MemoryUtil::gcSetWarningListener([](WarnEventType type) {
+    switch (type) {
+      case OUT_OF_MEMORY:
+      case FAILED_TO_EXPAND_HEAP:
+        if (s_currentIsolate) {
+          s_currentIsolate->onFatalError(nullptr, "Out of memory");
+        }
+        break;
+      default:
+        break;
+    }
+  });
 }
 
 IsolateWrap::~IsolateWrap() {
@@ -249,6 +272,7 @@ void IsolateWrap::set_array_buffer_allocator_shared(
 }
 
 void IsolateWrap::InitializeGlobalSlots() {
+  LWNODE_CALL_TRACE_ID(ISOWRAP);
   globalSlot_[internal::Internals::kUndefinedValueRootIndex] =
       EscargotShim::ValueWrap::createValue(ValueRef::createUndefined());
   globalSlot_[internal::Internals::kTheHoleValueRootIndex] =
@@ -294,7 +318,7 @@ void IsolateWrap::Initialize(const v8::Isolate::CreateParams& params) {
   auto platform = Platform::GetInstance();
   platform->setAllocator(array_buffer_allocator());
 
-  vmInstance_ = VMInstanceRef::create(platform);
+  vmInstance_ = VMInstanceRef::create();
   vmInstance_->setOnVMInstanceDelete([](VMInstanceRef* instance) {
     // Do Nothing
     LWNODE_CALL_TRACE_GC_START();
@@ -305,6 +329,51 @@ void IsolateWrap::Initialize(const v8::Isolate::CreateParams& params) {
   InitializeGlobalSlots();
 
   scheduled_exception_ = hole()->value();
+
+  // Register lwnode internal promise hook to create the internal field.
+  LWNODE_ONCE(LWNODE_DLOG_INFO("v8::Promise::kEmbedderFieldCount: %d",
+                               v8::Promise::kEmbedderFieldCount));
+  if (v8::Promise::kEmbedderFieldCount > 0) {
+    auto fn = [](ExecutionStateRef* state,
+                 VMInstanceRef::PromiseHookType type,
+                 PromiseObjectRef* promise,
+                 ValueRef* parent) {
+      // 1. create internal field on Init
+      if (type == VMInstanceRef::PromiseHookType::Init) {
+        LWNODE_DCHECK(v8::Promise::kEmbedderFieldCount > 0);
+        if (ObjectRefHelper::getInternalFieldCount(promise) == 0) {
+          ObjectRefHelper::setInternalFieldCount(promise,
+                                                 Promise::kEmbedderFieldCount);
+          /*
+            @note
+            In Node.js, promise internal field count is supposed to be set to 1.
+
+            reference:
+            - configure.py: v8_promise_internal_field_count = 1
+            - tools/v8_gypfiles/features.gypi: V8_PROMISE_INTERNAL_FIELD_COUNT
+            - deps/v8/src/heap/factory.cc: Factory::NewJSPromise()
+
+            v8 sets Smi::zero() to promise's internal fields, which are:
+              - Number from getInternalField
+              - nullptr from GetAlignedPointerFromInternalField
+
+            In lwnode, the returned value will be:
+              - Undefined from getInternalField
+              - nullptr from GetAlignedPointerFromInternalField
+
+            The difference from getInternalField seems not that meaningful in
+            Node.js.
+          */
+        }
+      }
+
+      // 2. run PromiseHook
+      IsolateWrap::GetCurrent()->RunPromiseHook(
+          (v8::PromiseHookType)type, promise, parent);
+    };
+
+    vmInstance_->registerPromiseHook(fn);
+  }
 }
 
 void IsolateWrap::Enter() {
@@ -349,7 +418,7 @@ void IsolateWrap::popHandleScope(v8Scope_t* handleScope) {
 }
 
 void IsolateWrap::addHandleToCurrentScope(HandleWrap* value) {
-  LWNODE_CALL_TRACE("%p", value);
+  LWNODE_CALL_TRACE_ID(ISOWRAP, "%p", value);
   LWNODE_CHECK(handleScopes_.size() >= 1);
   handleScopes_.back()->add(value);
 }
@@ -373,22 +442,6 @@ bool IsolateWrap::isCurrentScopeSealed() {
 }
 
 void IsolateWrap::pushContext(ContextWrap* context) {
-  LWNODE_CALL_TRACE_ID(ISOWRAP,
-                       "%p (%zu -> %zu)",
-                       context,
-                       contextScopes_.size(),
-                       contextScopes_.size() + 1);
-
-  if (contextScopes_.size() && (contextScopes_.back() != context)) {
-    LWNODE_DLOG_WARN(R"(multiple contexts exist:
-contextScopes_.back() != context means that we need to support multiple
-contexts. In Node.js at this time, one main Context associated with the
-Environment instance is used for most Node.js features (except writing
-MessagePort objects.) So, on purpose, we don't store Object's creation
-context which is related to Object::CreationContext().
-@note: we may ignore this warning if cctest not related runs.)");
-  }
-
   contextScopes_.push_back(context);
 }
 
@@ -513,24 +566,36 @@ void IsolateWrap::SetPendingExceptionAndMessage(
     GCManagedVector<Escargot::Evaluator::StackTraceData>& stackTraceData) {
   LWNODE_CALL_TRACE_ID(TRYCATCH);
 
-  auto exceptionObject =
-      ObjectRefHelper::toObject(GetCurrentContext()->get(), exception);
-  ObjectRefHelper::setExtraData(exceptionObject,
-                                new ExceptionObjectData(stackTraceData));
+  if (exception->isObject()) {
+    ObjectRefHelper::setExtraData(exception->asObject(),
+                                  new ExceptionObjectData(stackTraceData));
+  }
 
-  set_pending_exception(exceptionObject);
+  set_pending_exception(exception);
   // @note
   // pending_message_obj: v8::Message isn't created. Instead v8::Message
   // uses `stackTraceData.stackTraces()` directly to make a result requested.
   set_pending_message_obj(nullptr);
 }
 
+void IsolateWrap::Throw(Escargot::ExecutionStateRef* state) {
+  LWNODE_CALL_TRACE_ID(TRYCATCH);
+  LWNODE_DCHECK(has_scheduled_exception());
+
+  auto exception = scheduled_exception();
+  clear_scheduled_exception();
+  if (hasExternalTryCatch()) {
+    return;
+  }
+  state->throwException(exception);
+}
+
 ValueWrap** IsolateWrap::getGlobal(const int index) {
   LWNODE_CHECK(index < internal::Internals::kRootIndexSize);
   return &globalSlot_[index];
 }
 
-ValueWrap* IsolateWrap::undefined() {
+ValueWrap* IsolateWrap::undefined_value() {
   return globalSlot_[internal::Internals::kUndefinedValueRootIndex];
 }
 
@@ -581,10 +646,24 @@ void IsolateWrap::onFatalError(const char* location, const char* message) {
 }
 
 void IsolateWrap::SetPromiseHook(v8::PromiseHook callback) {
-  auto lwIsolate = GetCurrent();
-
   promise_hook_ = callback;
 
+  if (v8::Promise::kEmbedderFieldCount > 0) {
+    // @todo LWNODE_CHECK(isPromiseHookRegistered());
+    return;
+  }
+
+  // @note
+  // the following won't be used in Node.js since
+  // v8::Promise::kEmbedderFieldCount will be set to 1.
+  LWNODE_DCHECK(false);
+
+  auto lwIsolate = GetCurrent();
+  if (promise_hook_ == nullptr) {
+    lwIsolate->vmInstance()->unregisterPromiseHook();
+    return;
+  }
+
   auto fn = [](ExecutionStateRef* state,
                VMInstanceRef::PromiseHookType type,
                PromiseObjectRef* promise,
index 71578468048662ab796bd1f0854439af8b11855f..930bf0b5e3e54e4df938b64197cd0efa3f43d5ea 100755 (executable)
@@ -39,9 +39,10 @@ class Isolate : public gc {
 
   Escargot::ValueRef* scheduled_exception();
   bool has_scheduled_exception();
+  void set_scheduled_exception(Escargot::ValueRef* exception_obj);
   void clear_scheduled_exception();
 
-  Escargot::ObjectRef* pending_exception();
+  Escargot::ValueRef* pending_exception();
   bool has_pending_exception();
 
   Escargot::ValueRef* pending_message_obj();
@@ -72,6 +73,14 @@ class Isolate : public gc {
     prepare_stack_trace_callback_ = callback;
   }
 
+  bool HasPrepareStackTraceCallback() const {
+    return prepare_stack_trace_callback_ != nullptr;
+  }
+
+  v8::PrepareStackTraceCallback PrepareStackTraceCallback() const {
+    return prepare_stack_trace_callback_;
+  }
+
   void SetAbortOnUncaughtExceptionCallback(
       v8::Isolate::AbortOnUncaughtExceptionCallback callback) {
     abort_on_uncaught_exception_callback_ = callback;
@@ -83,9 +92,7 @@ class Isolate : public gc {
   }
 
  protected:
-  Escargot::ValueRef* scheduled_exception_{nullptr};
-
-  void set_pending_exception(Escargot::ObjectRef* exception_obj);
+  void set_pending_exception(Escargot::ValueRef* exception_obj);
   void set_pending_message_obj(Escargot::ValueRef* message_obj);
   void clear_pending_exception();
   void clear_pending_message_obj();
@@ -93,6 +100,11 @@ class Isolate : public gc {
   v8::TryCatch* getExternalTryCatchOnTop();
   bool hasExternalTryCatch();
 
+  // @important memory layout (IsolateData, kEmbedderDataOffset,
+  // kExternalMemoryOffset, kExternalMemoryLlimitOffset and so on) aren't
+  // considered.
+
+  Escargot::ValueRef* scheduled_exception_{nullptr};
   v8::PromiseRejectCallback promise_reject_callback_{nullptr};
   v8::PromiseHook promise_hook_{nullptr};
   v8::MessageCallback message_callback_{nullptr};
@@ -103,7 +115,7 @@ class Isolate : public gc {
 
  private:
   v8::TryCatch* try_catch_handler_{nullptr};
-  Escargot::ObjectRef* pending_exception_{nullptr};
+  Escargot::ValueRef* pending_exception_{nullptr};
   Escargot::ValueRef* pending_message_obj_{nullptr};
 };
 }  // namespace internal
@@ -183,7 +195,7 @@ class IsolateWrap final : public v8::internal::Isolate {
   VMInstanceRef* vmInstance() { return vmInstance_; }
 
   ValueWrap** getGlobal(const int idex);
-  ValueWrap* undefined();
+  ValueWrap* undefined_value();
   ValueWrap* hole() override;
   ValueWrap* null();
   ValueWrap* trueValue();
@@ -212,6 +224,8 @@ class IsolateWrap final : public v8::internal::Isolate {
 
   void onFatalError(const char* location, const char* message);
 
+  void Throw(Escargot::ExecutionStateRef* state);
+
   void lock_gc_release() { release_lock_.reset(this); }
   void unlock_gc_release() { release_lock_.release(); }
 
index 40b2035a302c5d4ca9a3467ec18ba3407c425a67..914a8d55bdf30faae00ff35b53799b0ad5b6e9c5 100644 (file)
@@ -39,7 +39,10 @@ static ValueRef* accessorPropertyGetter(
       wrapper->m_isolate, self, receiver, VAL(wrapper->m_data));
 
   auto v8Getter = wrapper->m_getter;
-  LWNODE_CHECK_NOT_NULL(v8Getter);
+  if (!v8Getter) {
+    return ValueRef::createUndefined();
+  }
+
   LWNODE_CALL_TRACE(
       "name: %s",
       VAL(wrapper->m_name)->value()->asString()->toStdUTF8String().c_str())
@@ -92,9 +95,7 @@ NativeDataAccessorPropertyDataWrap<T, F>::NativeDataAccessorPropertyDataWrap(
       m_name(*name),
       m_getter(getter),
       m_setter(setter),
-      m_data(*data) {
-  LWNODE_CHECK_NOT_NULL(getter);
-}
+      m_data(*data) {}
 
 Maybe<bool> ObjectUtils::SetAccessor(ObjectRef* esObject,
                                      IsolateWrap* lwIsolate,
diff --git a/lwnode/code/escargotshim/src/api/serializer.cc b/lwnode/code/escargotshim/src/api/serializer.cc
new file mode 100644 (file)
index 0000000..a7c365c
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "serializer.h"
+#include "context.h"
+#include "es-helper.h"
+#include "isolate.h"
+
+using namespace Escargot;
+using namespace v8;
+
+namespace EscargotShim {
+
+// base on v8/src/objects/value-serializer.cc
+
+static const uint32_t kLatestVersion = 13;
+
+enum class SerializationTag : uint8_t {
+  // version:uint32_t (if at beginning of data, sets version > 0)
+  kVersion = 0xFF,
+  // ignore
+  kPadding = '\0',
+  // refTableSize:uint32_t (previously used for sanity checks; safe to ignore)
+  kVerifyObjectCount = '?',
+  // Oddballs (no data).
+  kTheHole = '-',
+  kUndefined = '_',
+  kNull = '0',
+  kTrue = 'T',
+  kFalse = 'F',
+  // Number represented as 32-bit integer, ZigZag-encoded
+  // (like sint32 in protobuf)
+  kInt32 = 'I',
+  // Number represented as 32-bit unsigned integer, varint-encoded
+  // (like uint32 in protobuf)
+  kUint32 = 'U',
+  // Number represented as a 64-bit double.
+  // Host byte order is used (N.B. this makes the format non-portable).
+  kDouble = 'N',
+  // BigInt. Bitfield:uint32_t, then raw digits storage.
+  kBigInt = 'Z',
+  // byteLength:uint32_t, then raw data
+  kUtf8String = 'S',
+  kOneByteString = '"',
+  kTwoByteString = 'c',
+  // Reference to a serialized object. objectID:uint32_t
+  kObjectReference = '^',
+  // Beginning of a JS object.
+  kBeginJSObject = 'o',
+  // End of a JS object. numProperties:uint32_t
+  kEndJSObject = '{',
+  // Beginning of a sparse JS array. length:uint32_t
+  // Elements and properties are written as key/value pairs, like objects.
+  kBeginSparseJSArray = 'a',
+  // End of a sparse JS array. numProperties:uint32_t length:uint32_t
+  kEndSparseJSArray = '@',
+  // Beginning of a dense JS array. length:uint32_t
+  // |length| elements, followed by properties as key/value pairs
+  kBeginDenseJSArray = 'A',
+  // End of a dense JS array. numProperties:uint32_t length:uint32_t
+  kEndDenseJSArray = '$',
+  // Date. millisSinceEpoch:double
+  kDate = 'D',
+  // Boolean object. No data.
+  kTrueObject = 'y',
+  kFalseObject = 'x',
+  // Number object. value:double
+  kNumberObject = 'n',
+  // BigInt object. Bitfield:uint32_t, then raw digits storage.
+  kBigIntObject = 'z',
+  // String object, UTF-8 encoding. byteLength:uint32_t, then raw data.
+  kStringObject = 's',
+  // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data,
+  // flags:uint32_t.
+  kRegExp = 'R',
+  // Beginning of a JS map.
+  kBeginJSMap = ';',
+  // End of a JS map. length:uint32_t.
+  kEndJSMap = ':',
+  // Beginning of a JS set.
+  kBeginJSSet = '\'',
+  // End of a JS set. length:uint32_t.
+  kEndJSSet = ',',
+  // Array buffer. byteLength:uint32_t, then raw data.
+  kArrayBuffer = 'B',
+  // Array buffer (transferred). transferID:uint32_t
+  kArrayBufferTransfer = 't',
+  // View into an array buffer.
+  // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t
+  // For typed arrays, byteOffset and byteLength must be divisible by the size
+  // of the element.
+  // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an
+  // ObjectReference to one) serialized just before it. This is a quirk arising
+  // from the previous stack-based implementation.
+  kArrayBufferView = 'V',
+  // Shared array buffer. transferID:uint32_t
+  kSharedArrayBuffer = 'u',
+  // A wasm module object transfer. next value is its index.
+  kWasmModuleTransfer = 'w',
+  // The delegate is responsible for processing all following data.
+  // This "escapes" to whatever wire format the delegate chooses.
+  kHostObject = '\\',
+  // A transferred WebAssembly.Memory object. maximumPages:int32_t, then by
+  // SharedArrayBuffer tag and its data.
+  kWasmMemoryTransfer = 'm',
+  // A list of (subtag: ErrorTag, [subtag dependent data]). See ErrorTag for
+  // details.
+  kError = 'r',
+
+  // The following tags are reserved because they were in use in Chromium before
+  // the kHostObject tag was introduced in format version 13, at
+  //   v8           refs/heads/master@{#43466}
+  //   chromium/src refs/heads/master@{#453568}
+  //
+  // They must not be reused without a version check to prevent old values from
+  // starting to deserialize incorrectly. For simplicity, it's recommended to
+  // avoid them altogether.
+  //
+  // This is the set of tags that existed in SerializationTag.h at that time and
+  // still exist at the time of this writing (i.e., excluding those that were
+  // removed on the Chromium side because there should be no real user data
+  // containing them).
+  //
+  // It might be possible to also free up other tags which were never persisted
+  // (e.g. because they were used only for transfer) in the future.
+  kLegacyReservedMessagePort = 'M',
+  kLegacyReservedBlob = 'b',
+  kLegacyReservedBlobIndex = 'i',
+  kLegacyReservedFile = 'f',
+  kLegacyReservedFileIndex = 'e',
+  kLegacyReservedDOMFileSystem = 'd',
+  kLegacyReservedFileList = 'l',
+  kLegacyReservedFileListIndex = 'L',
+  kLegacyReservedImageData = '#',
+  kLegacyReservedImageBitmap = 'g',
+  kLegacyReservedImageBitmapTransfer = 'G',
+  kLegacyReservedOffscreenCanvas = 'H',
+  kLegacyReservedCryptoKey = 'K',
+  kLegacyReservedRTCCertificate = 'k',
+};
+
+ValueSerializer::ValueSerializer(v8::Isolate* isolate,
+                                 v8::ValueSerializer::Delegate* delegate)
+    : lwIsolate_(IsolateWrap::fromV8(isolate)), delegate_(delegate) {}
+
+void ValueSerializer::WriteHeader() {
+  WriteTag(SerializationTag::kVersion);
+  WriteVarint(kLatestVersion);
+}
+
+bool ValueSerializer::WriteJSObject(ObjectRef* object) {
+  if (LWNODE_UNLIKELY(out_of_memory_)) {
+    return ThrowIfOutOfMemory();
+  }
+  if (ObjectRefHelper::getInternalFieldCount(object) > 0) {
+    // TODO: WriteHostObject
+    LWNODE_UNIMPLEMENT;
+    return false;
+  }
+
+  auto esContext = lwIsolate_->GetCurrentContext()->get();
+  uint32_t propertiesWritten = 0;
+  WriteTag(SerializationTag::kBeginJSObject);
+  Escargot::ValueVectorRef* keys = nullptr;
+  EvalResult r = Evaluator::execute(
+      lwIsolate_->GetCurrentContext()->get(),
+      [](ExecutionStateRef* state,
+         ObjectRef* object,
+         Escargot::ValueVectorRef** keys) -> ValueRef* {
+        *keys = object->ownPropertyKeys(state);
+        return ValueRef::createUndefined();
+      },
+      object,
+      &keys);
+  LWNODE_CHECK(r.isSuccessful());
+
+  for (size_t i = 0; i < keys->size(); i++) {
+    auto propValueResult =
+        ObjectRefHelper::getProperty(esContext, object, keys->at(i));
+    LWNODE_CHECK(propValueResult.isSuccessful());
+    bool success =
+        WriteValue(keys->at(i)) && WriteValue(propValueResult.result);
+    if (!success) {
+      return false;
+    }
+    propertiesWritten++;
+    WriteTag(SerializationTag::kEndJSObject);
+    WriteVarint<uint32_t>(propertiesWritten);
+  }
+  return ThrowIfOutOfMemory();
+}
+
+bool ValueSerializer::WriteValue(ValueRef* value) {
+  if (value->isUndefined()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isNull()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isBoolean()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isNumber()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isBigInt()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isArrayBufferObject()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isDataViewObject()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isString()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isTypedArrayObject()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isArrayObject()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isSymbol()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isFunctionObject()) {
+    LWNODE_UNIMPLEMENT;
+  } else if (value->isObject()) {
+    return WriteJSObject(value->asObject());
+  } else {
+    LWNODE_UNIMPLEMENT;
+  }
+  return false;
+}
+
+// base on v8
+void ValueSerializer::WriteTag(SerializationTag tag) {
+  uint8_t raw_tag = static_cast<uint8_t>(tag);
+  WriteRawBytes(&raw_tag, sizeof(raw_tag));
+}
+
+// base on v8
+template <typename T>
+void ValueSerializer::WriteVarint(T value) {
+  // Writes an unsigned integer as a base-128 varint.
+  // The number is written, 7 bits at a time, from the least significant to the
+  // most significant 7 bits. Each byte, except the last, has the MSB set.
+  // See also https://developers.google.com/protocol-buffers/docs/encoding
+  static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
+                "Only unsigned integer types can be written as varints.");
+  uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
+  uint8_t* next_byte = &stack_buffer[0];
+  do {
+    *next_byte = (value & 0x7F) | 0x80;
+    next_byte++;
+    value >>= 7;
+  } while (value);
+  *(next_byte - 1) &= 0x7F;
+  WriteRawBytes(stack_buffer, next_byte - stack_buffer);
+}
+
+// base on v8
+void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
+  uint8_t* dest;
+  if (ReserveRawBytes(length).To(&dest) && length > 0) {
+    memcpy(dest, source, length);
+  }
+}
+
+// base on v8
+Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(size_t bytes) {
+  size_t old_size = buffer_size_;
+  size_t new_size = old_size + bytes;
+  if (LWNODE_UNLIKELY(new_size > buffer_capacity_)) {
+    bool ok;
+    if (!ExpandBuffer(new_size).To(&ok)) {
+      return Nothing<uint8_t*>();
+    }
+  }
+  buffer_size_ = new_size;
+  return Just(&buffer_[old_size]);
+}
+
+// base on v8
+Maybe<bool> ValueSerializer::ExpandBuffer(size_t required_capacity) {
+  LWNODE_CHECK(required_capacity > buffer_capacity_);
+  size_t requested_capacity =
+      std::max(required_capacity, buffer_capacity_ * 2) + 64;
+  size_t provided_capacity = 0;
+  void* new_buffer = nullptr;
+  if (delegate_) {
+    new_buffer = delegate_->ReallocateBufferMemory(
+        buffer_, requested_capacity, &provided_capacity);
+  } else {
+    new_buffer = realloc(buffer_, requested_capacity);
+    provided_capacity = requested_capacity;
+  }
+  if (new_buffer) {
+    LWNODE_CHECK(provided_capacity >= requested_capacity);
+    buffer_ = reinterpret_cast<uint8_t*>(new_buffer);
+    buffer_capacity_ = provided_capacity;
+    return Just(true);
+  } else {
+    out_of_memory_ = true;
+    return Nothing<bool>();
+  }
+}
+
+bool ValueSerializer::ThrowIfOutOfMemory() {
+  if (out_of_memory_) {
+    // TODO: thrwo internal error
+    return false;
+  }
+  return true;
+}
+
+}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/serializer.h b/lwnode/code/escargotshim/src/api/serializer.h
new file mode 100644 (file)
index 0000000..9018cc3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <EscargotPublic.h>
+#include <v8.h>
+
+using namespace Escargot;
+
+namespace EscargotShim {
+
+enum class SerializationTag : uint8_t;
+
+class IsolateWrap;
+
+class ValueSerializer {
+ public:
+  ValueSerializer(v8::Isolate* isolate,
+                  v8::ValueSerializer::Delegate* delegate);
+  void WriteHeader();
+  bool WriteValue(ValueRef* value);
+
+ private:
+  void WriteTag(SerializationTag tag);
+  template <typename T>
+  void WriteVarint(T value);
+  void WriteUint32(uint32_t value);
+  void WriteUint64(uint64_t value);
+  void WriteRawBytes(const void* source, size_t length);
+  void WriteDouble(double value);
+  bool WriteJSObject(ObjectRef* object);
+
+  v8::Maybe<uint8_t*> ReserveRawBytes(size_t bytes);
+  v8::Maybe<bool> ExpandBuffer(size_t required_capacity);
+
+  bool ThrowIfOutOfMemory();
+
+  IsolateWrap* lwIsolate_ = nullptr;
+  v8::ValueSerializer::Delegate* delegate_ = nullptr;
+  uint8_t* buffer_ = nullptr;
+  size_t buffer_size_ = 0;
+  size_t buffer_capacity_ = 0;
+  bool out_of_memory_ = false;
+};
+
+}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/stack-trace.cc b/lwnode/code/escargotshim/src/api/stack-trace.cc
new file mode 100644 (file)
index 0000000..d48642f
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stack-trace.h"
+#include "api.h"
+#include "base.h"
+#include "context.h"
+#include "isolate.h"
+
+using namespace Escargot;
+using namespace v8;
+
+namespace EscargotShim {
+
+class NativeDataAccessorPropertyDataForStackTrace
+    : public ObjectRef::NativeDataAccessorPropertyData {
+ public:
+  NativeDataAccessorPropertyDataForStackTrace(
+      bool isWritable,
+      bool isEnumerable,
+      bool isConfigurable,
+      ObjectRef::NativeDataAccessorPropertyGetter getter,
+      ObjectRef::NativeDataAccessorPropertySetter setter,
+      ValueVectorRef* stackTraceVector)
+      : NativeDataAccessorPropertyData(
+            isWritable, isEnumerable, isConfigurable, getter, setter),
+        stackTraceVector_(stackTraceVector) {}
+
+  ValueVectorRef* stackTraceVector() { return stackTraceVector_; }
+
+  void* operator new(size_t size) { return GC_MALLOC(size); }
+
+ private:
+  ValueVectorRef* stackTraceVector_;
+};
+
+static size_t getStackTraceLimit(ExecutionStateRef* state) {
+  auto errorObject = state->context()->globalObject()->get(
+      state, StringRef::createFromASCII("Error"));
+  LWNODE_CHECK(errorObject->isObject());
+
+  auto stackTraceLimitValue = errorObject->asObject()->get(
+      state, StringRef::createFromASCII("stackTraceLimit"));
+  LWNODE_CHECK(stackTraceLimitValue->isNumber());
+
+  return stackTraceLimitValue->asNumber();
+}
+
+static ValueRef* StackTraceGetter(
+    ExecutionStateRef* state,
+    ObjectRef* self,
+    ValueRef* receiver,
+    ObjectRef::NativeDataAccessorPropertyData* data) {
+  auto lwIsolate = IsolateWrap::GetCurrent();
+  auto lwContext = lwIsolate->GetCurrentContext();
+  auto accessorData =
+      reinterpret_cast<NativeDataAccessorPropertyDataForStackTrace*>(data);
+
+  if (lwIsolate->HasPrepareStackTraceCallback()) {
+    auto sites =
+        ArrayObjectRef::create(state, accessorData->stackTraceVector());
+    v8::MaybeLocal<v8::Value> callbackResult =
+        lwIsolate->PrepareStackTraceCallback()(
+            v8::Utils::NewLocal<Context>(lwIsolate->toV8(), lwContext),
+            v8::Utils::NewLocal<Value>(lwIsolate->toV8(), self),
+            v8::Utils::NewLocal<Array>(lwIsolate->toV8(), sites));
+
+    if (!callbackResult.IsEmpty()) {
+      Local<Value> callbackResultLocal;
+      if (callbackResult.ToLocal(&callbackResultLocal)) {
+        return CVAL(*callbackResultLocal)->value();
+      }
+    }
+  }
+
+  return ValueRef::createUndefined();
+}
+
+static bool StackTraceSetter(ExecutionStateRef* state,
+                             ObjectRef* self,
+                             ValueRef* receiver,
+                             ObjectRef::NativeDataAccessorPropertyData* data,
+                             ValueRef* setterInputData) {
+  LWNODE_RETURN_FALSE;
+}
+
+static ValueRef* captureStackTraceCallback(ExecutionStateRef* state,
+                                           ValueRef* thisValue,
+                                           size_t argc,
+                                           ValueRef** argv,
+                                           bool isConstructCall) {
+  if (argc < 1 || !argv[0]->isObject()) {
+    return ValueRef::createUndefined();
+  }
+
+  auto exceptionObject = argv[0]->asObject();
+  auto callSite = IsolateWrap::GetCurrent()->GetCurrentContext()->callSite();
+  auto stackTrace = state->computeStackTraceData();
+  auto stackTraceVector = ValueVectorRef::create();
+
+  std::string filterFunctionName;
+  if (argc > 1 && argv[1]->isFunctionObject()) {
+    auto name = argv[1]->asFunctionObject()->get(
+        state, StringRef::createFromASCII("name"));
+    if (name->isString()) {
+      filterFunctionName = name->asString()->toStdUTF8String();
+    }
+  }
+
+  // TODO: handle `constructorOpt` option :
+  // compare the address of constructorOpt function not name.
+  int stacktraceStartIdx = 1;
+  size_t stackTraceLimit = getStackTraceLimit(state) + stacktraceStartIdx;
+
+  for (size_t i = stacktraceStartIdx;
+       i < stackTraceLimit && i < stackTrace.size();
+       i++) {
+    if (!filterFunctionName.empty() &&
+        filterFunctionName == stackTrace[i].functionName->toStdUTF8String()) {
+      break;
+    }
+
+    stackTraceVector->pushBack(
+        callSite->instantiate(state->context(), stackTrace[i]));
+  }
+
+  exceptionObject->defineNativeDataAccessorProperty(
+      state,
+      StringRef::createFromUTF8("stack"),
+      new NativeDataAccessorPropertyDataForStackTrace(false,
+                                                      false,
+                                                      false,
+                                                      StackTraceGetter,
+                                                      StackTraceSetter,
+                                                      stackTraceVector));
+
+  return ValueRef::createUndefined();
+}
+
+ValueRef* StackTrace::createCaptureStackTrace(
+    Escargot::ExecutionStateRef* state) {
+  FunctionObjectRef::NativeFunctionInfo info(
+      AtomicStringRef::create(state->context(), "captureStackTrace"),
+      captureStackTraceCallback,
+      1,
+      true,
+      false);
+
+  return FunctionObjectRef::create(state, info);
+}
+
+static void setCallSitePrototype(
+    ContextRef* context,
+    ObjectTemplateRef* otpl,
+    const char* name,
+    Escargot::FunctionObjectRef::NativeFunctionPointer fn) {
+  auto length = strlen(name);
+
+  EvalResult r = Evaluator::execute(
+      context,
+      [](ExecutionStateRef* state,
+         const char* name,
+         size_t length,
+         Escargot::FunctionObjectRef::NativeFunctionPointer fn) -> ValueRef* {
+        return FunctionObjectRef::create(
+            state,
+            FunctionObjectRef::NativeFunctionInfo(
+                AtomicStringRef::create(state->context(), name, length),
+                fn,
+                0,
+                true,
+                false));
+      },
+      name,
+      length,
+      fn);
+  LWNODE_CHECK(r.isSuccessful());
+
+  otpl->set(
+      StringRef::createFromASCII(name, length), r.result, false, false, true);
+}
+
+static void injectSitePrototype(ContextRef* context, ObjectTemplateRef* otpl) {
+  setCallSitePrototype(
+      context,
+      otpl,
+      "getFunctionName",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        return data->functionName();
+      });
+
+  setCallSitePrototype(
+      context,
+      otpl,
+      "getFileName",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        return data->src();
+      });
+
+  setCallSitePrototype(
+      context,
+      otpl,
+      "getLineNumber",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        return ValueRef::create(data->loc().line);
+      });
+
+  setCallSitePrototype(
+      context,
+      otpl,
+      "getColumnNumber",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        return ValueRef::create(data->loc().column);
+      });
+
+  setCallSitePrototype(
+      context,
+      otpl,
+      "isEval",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        return ValueRef::create(data->isEval());
+      });
+
+  setCallSitePrototype(
+      context,
+      otpl,
+      "toString",
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         bool isNewExpression) -> ValueRef* {
+        auto data = ObjectRefHelper::getExtraData(thisValue->asObject())
+                        ->asStackTraceData();
+        std::ostringstream stream;
+        stream << data->functionName()->toStdUTF8String() << " ("
+               << data->src()->toStdUTF8String() << ":" << data->loc().line
+               << ":" << data->loc().column << ")";
+        auto string = stream.str();
+        return StringRef::createFromASCII(string.data(), string.length());
+      });
+}
+
+CallSite::CallSite(ContextRef* context) {
+  template_ = FunctionTemplateRef::create(
+      AtomicStringRef::create(context, "CallSite"),
+      0,
+      true,
+      true,
+      [](ExecutionStateRef* state,
+         ValueRef* thisValue,
+         size_t argc,
+         ValueRef** argv,
+         OptionalRef<ObjectRef> newTarget) -> ValueRef* {
+        return ValueRef::createUndefined();
+      });
+  injectSitePrototype(context, template_->prototypeTemplate());
+}
+
+ValueRef* CallSite::instantiate(ContextRef* context,
+                                const Evaluator::StackTraceData& data) {
+  auto callSite = template_->instanceTemplate()->instantiate(context);
+  ObjectRefHelper::setExtraData(callSite, new StackTraceData(data));
+  return callSite;
+};
+
+}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/stack-trace.h b/lwnode/code/escargotshim/src/api/stack-trace.h
new file mode 100644 (file)
index 0000000..4853f08
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <EscargotPublic.h>
+#include <GCUtil.h>
+
+using namespace Escargot;
+
+namespace EscargotShim {
+
+class StackTrace {
+ public:
+  static ValueRef* createCaptureStackTrace(ExecutionStateRef* state);
+};
+
+class CallSite : public gc {
+ public:
+  CallSite(Escargot::ContextRef* context);
+
+  ValueRef* instantiate(ContextRef* context,
+                        const Evaluator::StackTraceData& data);
+
+ private:
+  FunctionTemplateRef* template_;
+};
+
+}  // namespace EscargotShim
index 51f7f49890bcdc98cb9d437244309b3aec6c525e..fd241747768245c09175b90f38bad79cf8c1ae87 100644 (file)
@@ -20,6 +20,5 @@
 #include "utils/compiler.h"
 #include "utils/conversions-inl.h"
 #include "utils/gc.h"
-#include "utils/logger.h"
 #include "utils/misc.h"
 #include "utils/string.h"
index 6e802391eaaa513aabc93bc58c0472e506ab5802..0d4f4804624c42bfa71815959e278e7b689588d1 100644 (file)
@@ -19,7 +19,7 @@
 #include <execinfo.h>
 #endif
 #include "debug.h"
-#include "logger.h"
+#include "misc.h"
 
 namespace EscargotShim {
 
@@ -43,6 +43,11 @@ static const char* getCurrentProcessName() {
 #endif
 
 void DebugUtils::printStackTrace() {
+#if defined(NDEBUG)
+  if (EscargotShim::Flags::isInternalLogEnabled() == false) {
+    return;
+  }
+#endif
 #if defined(LWNODE_PLATFORM_LINUX)
   void* frames[kStackTraceFrameSize];
   static const char* processName = getCurrentProcessName();
diff --git a/lwnode/code/escargotshim/src/api/utils/flags.cc b/lwnode/code/escargotshim/src/api/utils/flags.cc
deleted file mode 100644 (file)
index 2407b15..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "flags.h"
-
-namespace EscargotShim {
-
-flag_t Flags::s_flags = FlagType::Empty;
-std::set<std::string> Flags::s_trace_ids;
-std::set<std::string> Flags::s_negative_trace_ids;
-
-bool Flags::isTraceCallEnabled(std::string id) {
-  if (!(s_flags & FlagType::TraceCall)) {
-    return false;
-  }
-
-  if (!s_trace_ids.empty()) {
-    if (s_trace_ids.find(id) == s_trace_ids.end()) {
-      return false;
-    }
-  }
-
-  if (!s_negative_trace_ids.empty()) {
-    if (s_negative_trace_ids.find(id) != s_negative_trace_ids.end()) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/utils/flags.h b/lwnode/code/escargotshim/src/api/utils/flags.h
deleted file mode 100644 (file)
index 2035e0b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <set>
-#include <string>
-#include "compiler.h"
-
-namespace EscargotShim {
-
-typedef uint16_t flag_t;
-
-enum FlagType : flag_t {
-  Empty = 0,
-  ExposeGC = 1 << 1,
-  UseStrict = 1 << 2,
-  DisableIdleGC = 1 << 3,
-  TopLevelWait = 1 << 4,
-  // lwnode
-  TraceCall = 1 << 5,
-  TraceGC = 1 << 6,
-  InternalLog = 1 << 7,
-};
-
-class LWNODE_EXPORT Flags {
- public:
-  static void set(flag_t flags) { s_flags = flags; }
-  static void add(flag_t flags) { s_flags |= flags; }
-  static flag_t get() { return s_flags; };
-
-  static bool isTraceCallEnabled(std::string id = "*");
-  static bool isTraceGCEnabled() { return s_flags & FlagType::TraceGC; }
-  static bool isInternalLogEnabled() { return s_flags & FlagType::InternalLog; }
-
-  static void setTraceCallId(std::string id) { s_trace_ids.insert(id); }
-  static void setNagativeTraceCallId(std::string id) {
-    s_negative_trace_ids.insert(id);
-  }
-
- private:
-  static std::set<std::string> s_trace_ids;
-  static std::set<std::string> s_negative_trace_ids;
-  static flag_t s_flags;
-};
-
-}  // namespace EscargotShim
index ba42490d90a7228b396d93c19d1da2defe87c879..a18dbb27d80c630d31424893b85e36d5ce682b00 100644 (file)
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <EscargotPublic.h>
+#include <cassert>
 #include <cstdarg>
 
 #include "gc.h"
@@ -27,7 +28,7 @@ class GCContainer : public gc {
  public:
   GCContainer() {}
 
-  explicit GCContainer(const size_t size, ...) {
+  explicit GCContainer(const size_t size, const size_t argc = 0, ...) {
     if (size) {
       buffer_ = (T*)Escargot::Memory::gcMalloc(sizeof(T) * size);
       size_ = size;
@@ -35,9 +36,10 @@ class GCContainer : public gc {
         new (&buffer_[i]) T();
       }
 
+      assert(argc <= size);
       std::va_list args;
-      va_start(args, size);
-      for (size_t i = 0; i < size; ++i) {
+      va_start(args, argc);
+      for (size_t i = 0; i < argc; ++i) {
         buffer_[i] = va_arg(args, T);
       }
       va_end(args);
index 56b0f2cde27c47fed9bfdc4092c7293142470a9c..b63025d2739bb2a5554c26c87ca1a5ba97d62960 100644 (file)
  */
 
 #include "gc.h"
+
 #include <EscargotPublic.h>
-#include <GCUtil.h>
-#include "flags.h"
-#include "logger.h"
+#include "misc.h"
 
 using namespace Escargot;
 
 #define LOG_HANDLER(msg, ...)                                                  \
   do {                                                                         \
     if (EscargotShim::Flags::isTraceGCEnabled()) {                             \
-      LWNODE_LOG_RAW(COLOR_DIM msg COLOR_RESET, ##__VA_ARGS__);                \
+      LWNODE_LOG_RAW(CLR_DIM msg CLR_RESET, ##__VA_ARGS__);                    \
     }                                                                          \
   } while (0)
 
 #define LOG_HANDLER_RAW(msg, ...)                                              \
   do {                                                                         \
-    if (EscargotShim::Flags::isTraceGCEnabled()) {                             \
-      printf(msg, ##__VA_ARGS__);                                              \
-    }                                                                          \
+    printf(msg, ##__VA_ARGS__);                                                \
   } while (0)
 
 // --- GCTracer ---
@@ -100,11 +97,11 @@ void GCTracer::printState() {
 
   for (const auto& it : registeredAddress_) {
     if (it.deallocated) {
-      LOG_HANDLER(COLOR_MAGENTA "deallocated: %s (%p)",
+      LOG_HANDLER(CLR_MAGENTA "deallocated: %s (%p)",
                   it.description.c_str(),
                   TO_GCPTR(it.ptr));
     } else {
-      LOG_HANDLER(COLOR_YELLOW "backtrace of %s (%p):\n",
+      LOG_HANDLER(CLR_YELLOW "backtrace of %s (%p):\n",
                   it.description.c_str(),
                   TO_GCPTR(it.ptr));
 
@@ -159,14 +156,35 @@ void MemoryUtil::gcStartStatsTrace() {
     prettyBytes(heap, sizeof(heap), nheap, g_filter);
     LOG_HANDLER("use %s, heap %s", use, heap);
   });
+}
 
-#ifdef ENABLE_GC_WARN
-  GC_set_warn_proc([](char* msg, GC_word arg) {
-    char formatted[1024];
-    snprintf(formatted, sizeof(formatted) - 1, msg, arg);
-    LOG_HANDLER("[WARN] %s\n", formatted);
-  });
+static thread_local MemoryUtil::OnGCWarnEventListener g_gcWarnEventListener;
+
+void MemoryUtil::gcSetWarningListener(OnGCWarnEventListener callback) {
+  if (g_gcWarnEventListener == nullptr) {
+    g_gcWarnEventListener = callback;
+
+    GC_set_warn_proc([](char* format, GC_word arg) {
+      /*
+        GC Warning: ...May lead to memory leak and poor performance
+        GC Warning: ...Failed to expand heap
+        GC Warning: Out of Memory! ... Returning NULL!
+      */
+      std::string message = format;
+
+#if !defined(NDEBUG)
+      LOG_HANDLER_RAW(format, arg);
 #endif
+
+      if (message.find("poor performance") != std::string::npos) {
+        g_gcWarnEventListener(POOR_PERFORMANCE);
+      } else if (message.find("Failed to expand heap") != std::string::npos) {
+        g_gcWarnEventListener(FAILED_TO_EXPAND_HEAP);
+      } else if (message.find("Out of Memory") != std::string::npos) {
+        g_gcWarnEventListener(OUT_OF_MEMORY);
+      }
+    });
+  }
 }
 
 void MemoryUtil::printGCStats() {
@@ -188,6 +206,7 @@ void MemoryUtil::printBacktrace(void* gcPtr) {
 }
 
 void MemoryUtil::printEveryReachableGCObjects() {
+#if !defined(ESCARGOT_THREADING)
   LOG_HANDLER("print reachable pointers -->\n");
   GC_gcollect();
   GC_disable();
@@ -226,6 +245,7 @@ void MemoryUtil::printEveryReachableGCObjects() {
   LOG_HANDLER("<-- end of print reachable pointers %fKB (count: %zu)\n",
               temp.totalRemainSize / 1024.f,
               temp.totalCount);
+#endif
 }
 
 void MemoryUtil::gcFull() {
index 2e39091bbd8ae659d1ff6b556148ccfec7887769..8f9d0e952852135b3694fb47ca9dd8951c42c16d 100644 (file)
@@ -159,8 +159,17 @@ class GCTracer {
   std::vector<Address> registeredAddress_;
 };
 
+enum WarnEventType {
+  POOR_PERFORMANCE,
+  FAILED_TO_EXPAND_HEAP,
+  OUT_OF_MEMORY,
+};
+
 class ESCARGOT_EXPORT MemoryUtil {
  public:
+  typedef void (*OnGCWarnEventListener)(WarnEventType type);
+
+  static void gcSetWarningListener(OnGCWarnEventListener callback);
   static void gcStartStatsTrace();
   static void gcEndStatsTrace();
   static void gcFull();
diff --git a/lwnode/code/escargotshim/src/api/utils/logger.cc b/lwnode/code/escargotshim/src/api/utils/logger.cc
deleted file mode 100644 (file)
index 5d6e854..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "logger.h"
-#include <regex>
-#include <set>
-#include <sstream>
-
-std::string getPrettyFunctionName(const std::string fullname) {
-  std::smatch match;
-  const std::regex re(R"(([\w\:~]+)\()");
-
-  if (std::regex_search(fullname, match, re) && match.size() > 1) {
-    return match.str(1);
-  }
-  return "";
-}
-
-std::string createCodeLocation(const char* functionName,
-                               const char* filename,
-                               const int line) {
-  std::ostringstream oss;
-  oss << getPrettyFunctionName(functionName) << " (" << filename << ":" << line
-      << ")" << std::endl;
-  return oss.str();
-}
-
-thread_local int s_indentCount = 0;
-thread_local int s_deltaCount = 0;
-thread_local std::set<std::string> s_counterIds;
-
-void IndentCounter::indent(std::string id) {
-  if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return;
-  s_deltaCount++;
-}
-
-void IndentCounter::unIndent(std::string id) {
-  if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return;
-  s_deltaCount--;
-}
-
-IndentCounter::IndentCounter(std::string id) {
-  id_ = id;
-
-  if (EscargotShim::Flags::isTraceCallEnabled(id) == false) return;
-
-  s_indentCount++;
-  s_counterIds.insert(id);
-}
-
-IndentCounter::~IndentCounter() {
-  if (EscargotShim::Flags::isTraceCallEnabled(id_) == false) return;
-
-  s_indentCount--;
-  s_counterIds.erase(id_);
-}
-
-std::string IndentCounter::getString(std::string id) {
-  if (s_counterIds.find(id) == s_counterIds.end()) {
-    return "";
-  }
-
-  assert(s_indentCount >= 0);
-
-  std::ostringstream oss;
-  int indentCount = s_indentCount + s_deltaCount;
-
-  if (s_deltaCount > 0) {
-    oss << s_deltaCount << " ";
-  }
-
-  for (int i = 1; i < std::min(30, indentCount); ++i) {
-    oss << "  ";
-  }
-
-  return oss.str();
-}
diff --git a/lwnode/code/escargotshim/src/api/utils/logger.h b/lwnode/code/escargotshim/src/api/utils/logger.h
deleted file mode 100644 (file)
index ab2aaec..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2021-present Samsung Electronics Co., Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <assert.h>
-#include <string.h>
-#include <cstdio>
-
-#include "flags.h"
-
-#define COLOR_RESET "\033[0m"
-#define COLOR_DIM "\033[0;2m"
-#define COLOR_RED "\033[0;31m"
-#define COLOR_GREEN "\033[0;32m"
-#define COLOR_GREY "\033[0;37m"
-#define COLOR_BLACK "\033[0;30m"
-#define COLOR_YELLOW "\033[0;33m"
-#define COLOR_BLUE "\033[0;34m"
-#define COLOR_MAGENTA "\033[0;35m"
-#define COLOR_CYAN "\033[0;36m"
-#define COLOR_DARKGREY "\033[01;30m"
-#define COLOR_BRED "\033[01;31m"
-#define COLOR_BYELLOW "\033[01;33m"
-#define COLOR_BBLUE "\033[01;34m"
-#define COLOR_BMAGENTA "\033[01;35m"
-#define COLOR_BCYAN "\033[01;36m"
-#define COLOR_BGREEN "\033[01;32m"
-#define COLOR_WHITE "\033[01;37m"
-#define COLOR_REDBG "\033[0;41m"
-
-std::string getPrettyFunctionName(const std::string fullname);
-std::string createCodeLocation(const char* functionName,
-                               const char* filename,
-                               const int line);
-inline const char* strBool(bool value) {
-  return value ? "True" : "False";
-}
-
-class IndentCounter {
- public:
-  IndentCounter(std::string id);
-  ~IndentCounter();
-  static std::string getString(std::string id = "");
-  static void indent(std::string id);
-  static void unIndent(std::string id);
-
- private:
-  std::string id_;
-};
-
-#define __FILENAME__                                                           \
-  (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
-#define TRACE_FMT "%s (%s:%d)"
-#define TRACE_ARGS __PRETTY_FUNCTION__, __FILENAME__, __LINE__
-#define TRACE_ARGS2                                                            \
-  getPrettyFunctionName(__PRETTY_FUNCTION__).c_str(), __FILENAME__, __LINE__
-
-#if !defined(NDEBUG)
-#define LWNODE_LOG_RAW(fmt, ...)                                               \
-  do {                                                                         \
-    fprintf(stderr, fmt "\n", ##__VA_ARGS__);                                  \
-  } while (0);
-#else
-#define LWNODE_LOG_RAW(fmt, ...)                                               \
-  do {                                                                         \
-    if (EscargotShim::Flags::isInternalLogEnabled() == true) {                 \
-      fprintf(stderr, fmt "\n", ##__VA_ARGS__);                                \
-    }                                                                          \
-  } while (0);
-#endif
-
-#define LWNODE_LOG_INFO(fmt, ...)                                              \
-  LWNODE_LOG_RAW("INFO " fmt COLOR_RESET, ##__VA_ARGS__);
-
-#define LWNODE_LOG_WARN(fmt, ...)                                              \
-  LWNODE_LOG_RAW(COLOR_YELLOW "WARN " fmt COLOR_RESET, ##__VA_ARGS__);
-
-#define LWNODE_LOG_ERROR(fmt, ...)                                             \
-  LWNODE_LOG_RAW(COLOR_BRED "ERROR " fmt COLOR_RESET, ##__VA_ARGS__);
-
-#define LWNODE_UNIMPLEMENT                                                     \
-  LWNODE_LOG_RAW(COLOR_RED "UNIMPLEMENTED " TRACE_FMT COLOR_RESET, TRACE_ARGS2);
-
-#define LWNODE_UNIMPLEMENT_IGNORED                                             \
-  LWNODE_LOG_RAW(COLOR_DIM "UNIMPLEMENTED (IGNORED) " TRACE_FMT COLOR_RESET,   \
-                 TRACE_ARGS2);
-
-#define LWNODE_UNIMPLEMENT_WORKAROUND                                          \
-  LWNODE_LOG_RAW(COLOR_DIM                                                     \
-                 "UNIMPLEMENTED (USE WORKAROUND) " TRACE_FMT COLOR_RESET,      \
-                 TRACE_ARGS2);
-
-// conditional loggers
-
-#if !defined(NDEBUG)
-#define LWNODE_DLOG_RAW(fmt, ...) LWNODE_LOG_RAW(fmt, ##__VA_ARGS__)
-#define LWNODE_DLOG_INFO(fmt, ...) LWNODE_LOG_INFO(fmt, ##__VA_ARGS__)
-#define LWNODE_DLOG_WARN(fmt, ...) LWNODE_LOG_WARN(fmt, ##__VA_ARGS__)
-#define LWNODE_DLOG_ERROR(fmt, ...) LWNODE_LOG_ERROR(fmt, ##__VA_ARGS__)
-#define FATAL(fmt, ...) LWNODE_LOG_ERROR(fmt, ##__VA_ARGS__)
-#else
-#define LWNODE_DLOG_RAW(fmt, ...)
-#define LWNODE_DLOG_INFO(fmt, ...)
-#define LWNODE_DLOG_WARN(fmt, ...)
-#define LWNODE_DLOG_ERROR(fmt, ...)
-#define FATAL(fmt, ...)
-#endif
diff --git a/lwnode/code/escargotshim/src/api/utils/logger/flags.cc b/lwnode/code/escargotshim/src/api/utils/logger/flags.cc
new file mode 100644 (file)
index 0000000..2407b15
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flags.h"
+
+namespace EscargotShim {
+
+flag_t Flags::s_flags = FlagType::Empty;
+std::set<std::string> Flags::s_trace_ids;
+std::set<std::string> Flags::s_negative_trace_ids;
+
+bool Flags::isTraceCallEnabled(std::string id) {
+  if (!(s_flags & FlagType::TraceCall)) {
+    return false;
+  }
+
+  if (!s_trace_ids.empty()) {
+    if (s_trace_ids.find(id) == s_trace_ids.end()) {
+      return false;
+    }
+  }
+
+  if (!s_negative_trace_ids.empty()) {
+    if (s_negative_trace_ids.find(id) != s_negative_trace_ids.end()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/utils/logger/flags.h b/lwnode/code/escargotshim/src/api/utils/logger/flags.h
new file mode 100644 (file)
index 0000000..e6b613f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <set>
+#include <string>
+
+#if !defined(LWNODE_EXPORT)
+#define LWNODE_EXPORT __attribute__((visibility("default")))
+#define LWNODE_LOCAL __attribute__((visibility("hidden")))
+#endif
+
+namespace EscargotShim {
+
+typedef uint16_t flag_t;
+
+enum FlagType : flag_t {
+  Empty = 0,
+  ExposeGC = 1 << 1,
+  UseStrict = 1 << 2,
+  DisableIdleGC = 1 << 3,
+  TopLevelWait = 1 << 4,
+  // lwnode
+  TraceCall = 1 << 5,
+  TraceGC = 1 << 6,
+  InternalLog = 1 << 7,
+};
+
+class LWNODE_EXPORT Flags {
+ public:
+  static void set(flag_t flags) { s_flags = flags; }
+  static void add(flag_t flags) { s_flags |= flags; }
+  static flag_t get() { return s_flags; };
+
+  static bool isTraceCallEnabled(std::string id = "*");
+  static bool isTraceGCEnabled() { return s_flags & FlagType::TraceGC; }
+  static bool isInternalLogEnabled() { return s_flags & FlagType::InternalLog; }
+
+  static void setTraceCallId(std::string id) { s_trace_ids.insert(id); }
+  static void setNagativeTraceCallId(std::string id) {
+    s_negative_trace_ids.insert(id);
+  }
+
+ private:
+  static std::set<std::string> s_trace_ids;
+  static std::set<std::string> s_negative_trace_ids;
+  static flag_t s_flags;
+};
+
+}  // namespace EscargotShim
diff --git a/lwnode/code/escargotshim/src/api/utils/logger/logger.cc b/lwnode/code/escargotshim/src/api/utils/logger/logger.cc
new file mode 100644 (file)
index 0000000..88ee28c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "logger.h"
+#include <assert.h>
+#include <regex>
+#include <set>
+#include <sstream>
+
+std::string getPrettyFunctionName(const std::string fullname) {
+  std::smatch match;
+  const std::regex re(R"(([\w\:~]+)\()");
+
+  if (std::regex_search(fullname, match, re) && match.size() > 1) {
+    return match.str(1);
+  }
+  return "";
+}
+
+std::string createCodeLocation(const char* functionName,
+                               const char* filename,
+                               const int line) {
+  std::ostringstream oss;
+  oss << getPrettyFunctionName(functionName) << " (" << filename << ":" << line
+      << ")" << std::endl;
+  return oss.str();
+}
+
+thread_local int s_indentCount = 0;
+thread_local int s_deltaCount = 0;
+thread_local std::set<std::string> s_counterIds;
+
+#define FORCE_ENABLE_INDENT_ID "NODE"
+
+static bool isIndentIdEnabled(std::string id) {
+  if (id == FORCE_ENABLE_INDENT_ID) {
+    return true;
+  }
+  return EscargotShim::Flags::isTraceCallEnabled(id);
+}
+
+void IndentCounter::indent(std::string id) {
+  if (isIndentIdEnabled(id) == false) return;
+  s_deltaCount++;
+}
+
+void IndentCounter::unIndent(std::string id) {
+  if (isIndentIdEnabled(id) == false) return;
+  s_deltaCount--;
+}
+
+IndentCounter::IndentCounter(std::string id) {
+  id_ = id;
+
+  if (isIndentIdEnabled(id) == false) return;
+
+  s_indentCount++;
+  s_counterIds.insert(id);
+}
+
+IndentCounter::~IndentCounter() {
+  if (isIndentIdEnabled(id_) == false) return;
+
+  s_indentCount--;
+  s_counterIds.erase(id_);
+}
+
+std::string IndentCounter::getString(std::string id) {
+  if (s_counterIds.find(id) == s_counterIds.end()) {
+    return "";
+  }
+
+  assert(s_indentCount >= 0);
+
+  std::ostringstream oss;
+  int indentCount = s_indentCount + s_deltaCount;
+
+  if (s_deltaCount > 0) {
+    oss << s_deltaCount << " ";
+  }
+
+  for (int i = 1; i < std::min(30, indentCount); ++i) {
+    oss << "  ";
+  }
+
+  return oss.str();
+}
diff --git a/lwnode/code/escargotshim/src/api/utils/logger/logger.h b/lwnode/code/escargotshim/src/api/utils/logger/logger.h
new file mode 100644 (file)
index 0000000..5ba6d71
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string.h>
+#include <cstdio>
+
+#include "flags.h"
+
+#define CLR_RESET "\033[0m"
+#define CLR_DIM "\033[0;2m"
+#define CLR_RED "\033[0;31m"
+#define CLR_GREEN "\033[0;32m"
+#define CLR_GREY "\033[0;37m"
+#define CLR_BLACK "\033[0;30m"
+#define CLR_YELLOW "\033[0;33m"
+#define CLR_BLUE "\033[0;34m"
+#define CLR_MAGENTA "\033[0;35m"
+#define CLR_CYAN "\033[0;36m"
+#define CLR_DARKGREY "\033[01;30m"
+#define CLR_BRED "\033[01;31m"
+#define CLR_BYELLOW "\033[01;33m"
+#define CLR_BBLUE "\033[01;34m"
+#define CLR_BMAGENTA "\033[01;35m"
+#define CLR_BCYAN "\033[01;36m"
+#define CLR_BGREEN "\033[01;32m"
+#define CLR_WHITE "\033[01;37m"
+#define CLR_REDBG "\033[0;41m"
+
+std::string getPrettyFunctionName(const std::string fullname);
+std::string createCodeLocation(const char* functionName,
+                               const char* filename,
+                               const int line);
+inline const char* strBool(bool value) {
+  return value ? "True" : "False";
+}
+
+class IndentCounter {
+ public:
+  IndentCounter(std::string id);
+  ~IndentCounter();
+  static std::string getString(std::string id = "");
+  static void indent(std::string id);
+  static void unIndent(std::string id);
+
+ private:
+  std::string id_;
+};
+
+#define __FILENAME__                                                           \
+  (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#define TRACE_FMT "%s (%s:%d)"
+#define TRACE_ARGS __PRETTY_FUNCTION__, __FILENAME__, __LINE__
+#define TRACE_ARGS2                                                            \
+  getPrettyFunctionName(__PRETTY_FUNCTION__).c_str(), __FILENAME__, __LINE__
+
+#define LWNODE_LOG_RAW(fmt, ...)                                               \
+  do {                                                                         \
+    fprintf(stderr, fmt "\n", ##__VA_ARGS__);                                  \
+  } while (0);
+
+#if !defined(NDEBUG)
+#define LWNODE_LOG_INTERNAL(fmt, ...) LWNODE_LOG_RAW(fmt, ##__VA_ARGS__);
+#else
+#define LWNODE_LOG_INTERNAL(fmt, ...)                                          \
+  if (EscargotShim::Flags::isInternalLogEnabled()) {                           \
+    LWNODE_LOG_RAW(fmt, ##__VA_ARGS__);                                        \
+  }
+#endif
+
+#define LWNODE_LOG_INFO(fmt, ...)                                              \
+  LWNODE_LOG_INTERNAL("INFO " fmt CLR_RESET, ##__VA_ARGS__);
+
+#define LWNODE_LOG_WARN(fmt, ...)                                              \
+  LWNODE_LOG_INTERNAL(CLR_YELLOW "WARN " fmt CLR_RESET, ##__VA_ARGS__);
+
+#define LWNODE_LOG_ERROR(fmt, ...)                                             \
+  LWNODE_LOG_INTERNAL(CLR_BRED "ERROR " fmt CLR_RESET, ##__VA_ARGS__);
+
+#define LWNODE_UNIMPLEMENT                                                     \
+  LWNODE_LOG_INTERNAL(CLR_RED "UNIMPLEMENTED " TRACE_FMT CLR_RESET,            \
+                      TRACE_ARGS2);
+
+#define LWNODE_UNIMPLEMENT_IGNORED                                             \
+  LWNODE_LOG_INTERNAL(CLR_DIM "UNIMPLEMENTED (IGNORED) " TRACE_FMT CLR_RESET,  \
+                      TRACE_ARGS2);
+
+#define LWNODE_UNIMPLEMENT_WORKAROUND                                          \
+  LWNODE_LOG_INTERNAL(CLR_DIM                                                  \
+                      "UNIMPLEMENTED (USE WORKAROUND) " TRACE_FMT CLR_RESET,   \
+                      TRACE_ARGS2);
+
+// conditional loggers
+
+#if !defined(NDEBUG)
+#define LWNODE_DLOG_RAW(fmt, ...) LWNODE_LOG_RAW(fmt, ##__VA_ARGS__)
+#define LWNODE_DLOG_INFO(fmt, ...) LWNODE_LOG_INFO(fmt, ##__VA_ARGS__)
+#define LWNODE_DLOG_WARN(fmt, ...) LWNODE_LOG_WARN(fmt, ##__VA_ARGS__)
+#define LWNODE_DLOG_ERROR(fmt, ...) LWNODE_LOG_ERROR(fmt, ##__VA_ARGS__)
+#define FATAL(fmt, ...) LWNODE_LOG_ERROR(fmt, ##__VA_ARGS__)
+#else
+#define LWNODE_DLOG_RAW(fmt, ...)
+#define LWNODE_DLOG_INFO(fmt, ...)
+#define LWNODE_DLOG_WARN(fmt, ...)
+#define LWNODE_DLOG_ERROR(fmt, ...)
+#define FATAL(fmt, ...)
+#endif
diff --git a/lwnode/code/escargotshim/src/api/utils/logger/trace.h b/lwnode/code/escargotshim/src/api/utils/logger/trace.h
new file mode 100644 (file)
index 0000000..aec155d
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "flags.h"
+#include "logger.h"
+
+#if !defined(NDEBUG)
+
+#define FIRST_ARG(N, ...) N
+#define LEFT_ARGS(N, ...) , ##__VA_ARGS__
+#define TRACE_TAG_FMT CLR_DIM "TRACE (%-10s)"
+#define TRACE_TAG_ARG(id) std::string(id).substr(0, 10).c_str()
+#define COUNTER_FMT "%s"
+#define COUNTER_ARG(id) IndentCounter::getString(id).c_str()
+
+#define LWNODE_CALL_TRACE_ID_LOG(id, ...)                                      \
+  if (EscargotShim::Flags::isTraceCallEnabled(#id)) {                          \
+    LWNODE_DLOG_RAW(TRACE_TAG_FMT " " COUNTER_FMT TRACE_FMT                    \
+                                  " " CLR_RESET FIRST_ARG(__VA_ARGS__)         \
+                                      CLR_RESET,                               \
+                    TRACE_TAG_ARG(#id),                                        \
+                    COUNTER_ARG(#id),                                          \
+                    TRACE_ARGS2 LEFT_ARGS(__VA_ARGS__));                       \
+  }
+
+#define LWNODE_CALL_TRACE_ID(id, ...)                                          \
+  IndentCounter __counter(#id);                                                \
+  LWNODE_CALL_TRACE_ID_LOG(id, __VA_ARGS__)
+
+#define LWNODE_CALL_TRACE_ID_INDENT(id) IndentCounter::indent(#id);
+#define LWNODE_CALL_TRACE_ID_UNINDENT(id) IndentCounter::unIndent(#id);
+
+#define LWNODE_CALL_TRACE(msg, ...)                                            \
+  LWNODE_CALL_TRACE_ID(COMMON, msg, ##__VA_ARGS__);
+#define LWNODE_CALL_TRACE_LOG(msg, ...)                                        \
+  LWNODE_CALL_TRACE_ID_LOG(COMMON, msg, ##__VA_ARGS__);
+#define LWNODE_CALL_TRACE_INDENT() LWNODE_CALL_TRACE_ID_INDENT(COMMON);
+#define LWNODE_CALL_TRACE_UNINDENT() LWNODE_CALL_TRACE_ID_UNINDENT(COMMON);
+
+#define LWNODE_CALL_TRACE_GC_START(msg, ...)                                   \
+  if (EscargotShim::Flags::isTraceCallEnabled("gc")) {                         \
+    LWNODE_DLOG_INFO("GC: %s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__);       \
+  }
+
+#define LWNODE_CALL_TRACE_GC_END(msg, ...)                                     \
+  if (EscargotShim::Flags::isTraceCallEnabled("gc")) {                         \
+    LWNODE_DLOG_INFO("GC: /%s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__);      \
+  }
+
+#else
+#define LWNODE_CALL_TRACE_ID(...)
+#define LWNODE_CALL_TRACE_ID_LOG(...)
+#define LWNODE_CALL_TRACE_ID_INDENT(...)
+#define LWNODE_CALL_TRACE_ID_UNINDENT(...)
+
+#define LWNODE_CALL_TRACE(...)
+#define LWNODE_CALL_TRACE_LOG(...)
+#define LWNODE_CALL_TRACE_INDENT()
+#define LWNODE_CALL_TRACE_UNINDENT()
+#define LWNODE_CALL_TRACE_GC_START(...)
+#define LWNODE_CALL_TRACE_GC_END(...)
+#endif
+
+#if !defined(NDEBUG)
+#define LWNODE_ONCE(operation)                                                 \
+  do {                                                                         \
+    static bool once##__LINE__ = false;                                        \
+    if (!once##__LINE__) {                                                     \
+      operation;                                                               \
+      once##__LINE__ = true;                                                   \
+    }                                                                          \
+  } while (0)
+#else
+#define LWNODE_ONCE(operation)
+#endif
index 8b570f4f50870a871f659b92d4270f7e8294ff4b..5205bca170ce950ed2b851a27b2d9a824171f785 100644 (file)
@@ -18,8 +18,7 @@
 
 #include <assert.h>
 #include "debug.h"
-#include "flags.h"
-#include "logger.h"
+#include "logger/trace.h"
 
 /* UNLIKELY */
 #ifndef LWNODE_UNLIKELY
 
 /* CHECK */
 // Use CHECK when abort should occurs if the condition fails
-#define CHECK_FMT COLOR_REDBG "CHECK FAILED" COLOR_RESET " "
+#define CHECK_FMT CLR_REDBG "CHECK FAILED" CLR_RESET " "
 
 #define _LWNODE_CHECK_FAILED_HANDLER(msg, ...)                                 \
-  LWNODE_LOG_RAW(CHECK_FMT msg "\n\t " TRACE_FMT, ##__VA_ARGS__, TRACE_ARGS);  \
+  LWNODE_LOG_INTERNAL(                                                         \
+      CHECK_FMT msg "\n\t " TRACE_FMT, ##__VA_ARGS__, TRACE_ARGS);             \
   EscargotShim::DebugUtils::printStackTrace();                                 \
   std::abort();
 
 #define LWNODE_DCHECK_NOT_NULL(x)
 #define LWNODE_DCHECK_MSG(condition, msg, ...)
 #endif
-
-#if !defined(NDEBUG)
-
-#define FIRST_ARG(N, ...) N
-#define LEFT_ARGS(N, ...) , ##__VA_ARGS__
-#define TRACE_TAG_FMT COLOR_DIM "TRACE (%-10s)"
-#define TRACE_TAG_ARG(id) std::string(id).substr(0, 10).c_str()
-#define COUNTER_FMT "%s"
-#define COUNTER_ARG(id) IndentCounter::getString(id).c_str()
-
-#define LWNODE_CALL_TRACE_ID(id, ...)                                          \
-  IndentCounter __counter(#id);                                                \
-  if (EscargotShim::Flags::isTraceCallEnabled(#id)) {                          \
-    LWNODE_DLOG_RAW(TRACE_TAG_FMT " " COUNTER_FMT TRACE_FMT                    \
-                                  " " COLOR_RESET FIRST_ARG(__VA_ARGS__)       \
-                                      COLOR_RESET,                             \
-                    TRACE_TAG_ARG(#id),                                        \
-                    COUNTER_ARG(#id),                                          \
-                    TRACE_ARGS2 LEFT_ARGS(__VA_ARGS__));                       \
-  }
-
-#define LWNODE_CALL_TRACE_ID_LOG(id, ...)                                      \
-  if (EscargotShim::Flags::isTraceCallEnabled(#id)) {                          \
-    LWNODE_DLOG_RAW(TRACE_TAG_FMT                                              \
-                    " " COUNTER_FMT COLOR_RESET FIRST_ARG(__VA_ARGS__)         \
-                        COLOR_RESET,                                           \
-                    TRACE_TAG_ARG(#id),                                        \
-                    COUNTER_ARG(#id) LEFT_ARGS(__VA_ARGS__));                  \
-  }
-
-#define LWNODE_CALL_TRACE_ID_INDENT(id) IndentCounter::indent(#id);
-#define LWNODE_CALL_TRACE_ID_UNINDENT(id) IndentCounter::unIndent(#id);
-
-#define LWNODE_CALL_TRACE(msg, ...)                                            \
-  LWNODE_CALL_TRACE_ID(COMMON, msg, ##__VA_ARGS__);
-#define LWNODE_CALL_TRACE_LOG(msg, ...)                                        \
-  LWNODE_CALL_TRACE_ID_LOG(COMMON, msg, ##__VA_ARGS__);
-#define LWNODE_CALL_TRACE_INDENT() LWNODE_CALL_TRACE_ID_INDENT(COMMON);
-#define LWNODE_CALL_TRACE_UNINDENT() LWNODE_CALL_TRACE_ID_UNINDENT(COMMON);
-
-#define LWNODE_CALL_TRACE_GC_START(msg, ...)                                   \
-  if (EscargotShim::Flags::isTraceCallEnabled("gc")) {                         \
-    LWNODE_DLOG_INFO("GC: %s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__);       \
-  }
-
-#define LWNODE_CALL_TRACE_GC_END(msg, ...)                                     \
-  if (EscargotShim::Flags::isTraceCallEnabled("gc")) {                         \
-    LWNODE_DLOG_INFO("GC: /%s (%s:%d): " msg, TRACE_ARGS, ##__VA_ARGS__);      \
-  }
-
-#else
-#define LWNODE_CALL_TRACE_ID(...)
-#define LWNODE_CALL_TRACE_ID_LOG(...)
-#define LWNODE_CALL_TRACE_ID_INDENT(...)
-#define LWNODE_CALL_TRACE_ID_UNINDENT(...)
-
-#define LWNODE_CALL_TRACE(...)
-#define LWNODE_CALL_TRACE_LOG(...)
-#define LWNODE_CALL_TRACE_INDENT()
-#define LWNODE_CALL_TRACE_UNINDENT()
-#define LWNODE_CALL_TRACE_GC_START(...)
-#define LWNODE_CALL_TRACE_GC_END(...)
-#endif
-
-#if !defined(NDEBUG)
-#define LWNODE_ONCE(operation)                                                 \
-  do {                                                                         \
-    static bool once##__LINE__ = false;                                        \
-    if (!once##__LINE__) {                                                     \
-      operation;                                                               \
-      once##__LINE__ = true;                                                   \
-    }                                                                          \
-  } while (0)
-#else
-#define LWNODE_ONCE(operation)
-#endif
diff --git a/lwnode/code/escargotshim/src/api/utils/smaps.cc b/lwnode/code/escargotshim/src/api/utils/smaps.cc
new file mode 100644 (file)
index 0000000..406273e
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @author lwnode-contributors
+ */
+
+#include "smaps.h"
+#include <unistd.h>
+#include <cassert>
+#include <fstream>
+#include <iomanip>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+// utils
+
+bool existsFile(const std::string& path) {
+  std::ifstream fs(path);
+  return fs.good();
+}
+
+std::string getCurrentTimeString(std::string format) {
+  std::stringstream ss;
+  auto time = std::time(nullptr);
+  ss << std::put_time(std::localtime(&time), format.c_str());
+  return ss.str();
+}
+
+static std::vector<std::string> tokenize(const std::string& str) {
+  std::vector<std::string> result;
+  std::string token;
+  std::stringstream ss(str);
+
+  while (ss >> token) {
+    result.push_back(token);
+  }
+  return result;
+}
+
+static std::vector<std::string> tokenize(const std::string& str,
+                                         const char delimiter) {
+  std::vector<std::string> result;
+  std::string token;
+  std::stringstream ss(str);
+
+  while (std::getline(ss, token, delimiter)) {
+    result.push_back(token);
+  }
+  return result;
+}
+
+static inline bool startsWith(const std::string& string,
+                              const std::string& prefix) {
+  return (string.rfind(prefix, 0) == 0);
+}
+
+static std::string trimString(std::string& str,
+                              const std::string& delimiters = " \t\n\v\f\r") {
+  str.erase(str.find_last_not_of(delimiters) + 1);
+  str.erase(0, str.find_first_not_of(delimiters));
+  return str;
+}
+
+// parseSmaps
+
+static std::string getMemoryRegionString(std::string pathname) {
+  std::string type = "ANONYMOUS";
+  if (pathname[0] != '/') {
+    if (startsWith(pathname, "[stack") || startsWith(pathname, "[tstack")) {
+      type = "STACK";
+    } else if (startsWith(pathname, "[heap") || pathname.empty()) {
+      type = "HEAP/MMAP";
+    } else if (startsWith(pathname, "[vdso")) {
+      type = "VDSO";
+    }
+  } else if (existsFile(pathname)) {
+    type = "LIBRARY";
+  }
+  return type;
+}
+
+std::vector<SmapContents> parseSmaps(std::istream& input) {
+  std::vector<SmapContents> result;
+  std::string line;
+
+  SmapContents map;
+  bool isHeaderFound = false;
+
+  while (std::getline(input, line, '\n')) {
+    if (line.find("-") != std::string::npos) {
+      isHeaderFound = true;
+      if (map.empty() == false) {
+        result.push_back(map);
+        map.clear();
+      }
+      /*
+        The format is:
+
+        address           perms offset  dev   inode      pathname
+
+        08048000-08049000 r-xp 00000000 03:00 8312       /opt/test
+        08049000-0804a000 rw-p 00001000 03:00 8312       /opt/test
+        0804a000-0806b000 rw-p 00000000 00:00 0          [heap]
+        a7cb1000-a7cb2000 ---p 00000000 00:00 0
+      */
+      auto tokens = tokenize(line);
+      auto address = tokenize(tokens[0], '-');
+
+      map[kStartingAddr] = address[0];
+      map[kEndingAddr] = address[1];
+      map[kPermissions] = tokens[1].substr(tokens[1].size() - 1) +
+                          tokens[1].substr(0, tokens[1].size() - 1);
+
+      map[kOffset] = tokens[2];
+      map[kDev] = tokens[3];
+      map[kInode] = tokens[4];
+
+      std::string pathname = (tokens.size() == 6) ? tokens[5] : "";
+      map[kPathname] = pathname;
+      map[kRegion] = getMemoryRegionString(pathname);
+    } else {
+      if (isHeaderFound == false) {
+        continue;
+      }
+      /*
+        The format is:
+
+        Size:               1084 kB
+        KernelPageSize:        4 kB
+        MMUPageSize:           4 kB
+        Rss:                 892 kB
+        Pss:                 374 kB
+        Shared_Clean:        892 kB
+        Shared_Dirty:          0 kB
+        Private_Clean:         0 kB
+        Private_Dirty:         0 kB
+        Referenced:          892 kB
+        Anonymous:             0 kB
+        LazyFree:              0 kB
+        AnonHugePages:         0 kB
+        ShmemPmdMapped:        0 kB
+        Shared_Hugetlb:        0 kB
+        Private_Hugetlb:       0 kB
+        Swap:                  0 kB
+        SwapPss:               0 kB
+        KernelPageSize:        4 kB
+        MMUPageSize:           4 kB
+        Locked:                0 kB
+        THPeligible:           0
+      */
+      auto tokens = tokenize(line, ':');
+      if (tokens.size() == 2) {
+        std::string count = trimString(tokens[1]);
+        if (count.rfind(" kB") != std::string::npos) {
+          count = count.substr(0, count.size() - 3);  // 3: " kB"
+        }
+        map[trimString(tokens[0])] = count;
+      }
+    }
+  }
+
+  return result;
+}
+
+std::vector<SmapContents> parseSmaps(std::string pid) {
+  auto smapsPath = "/proc/" + pid + "/smaps";
+  if (existsFile(smapsPath)) {
+    std::ifstream input("/proc/" + pid + "/smaps");
+    return parseSmaps(input);
+  }
+  return std::vector<SmapContents>();
+}
+
+size_t calculateTotal(std::vector<SmapContents>& smaps, const char* key) {
+  size_t total = 0;
+  for (auto& smap : smaps) {
+    total += std::stoull(smap[key]);
+  }
+  return total;
+}
+
+size_t calculateTotalPssSwap(std::vector<SmapContents>& smaps) {
+  size_t total = 0;
+  for (auto& smap : smaps) {
+    total += (std::stoull(smap["Pss"]) + std::stoull(smap["Swap"]));
+  }
+  return total;
+}
+
+size_t calculateTotalRss(std::vector<SmapContents>& smaps) {
+  size_t total = 0;
+  for (auto& smap : smaps) {
+    total += std::stoull(smap["Rss"]);
+  }
+  return total;
+}
+
+std::string getMemorySnapshotString(std::vector<SmapContents>& smaps,
+                                    SnapshotStringOption option) {
+  std::stringstream output;
+
+  if (option & kShowFullInfo) {
+    output << "perms,start-addr,end-addr,vm_name,offset,dev,inode,vm_size,rss,"
+              "pss,swap,total_pss";
+    if (option & kShowRegion) {
+      output << ",region";
+    }
+    output << std::endl;
+  } else {
+    output
+        << "perms,start-addr,end-addr,vm_name,vm_size,rss,pss,swap,total_pss";
+    if (option & kShowRegion) {
+      output << ",region";
+    }
+    output << std::endl;
+  }
+
+  const int kApiSystemPointerSize = sizeof(void*);
+  const int kAlignSize = kApiSystemPointerSize * 2 - 4;
+
+  for (auto& smap : smaps) {
+    auto totalPass = std::stoull(smap["Pss"]) + std::stoull((smap["Swap"]));
+    output << smap[kPermissions] << ","
+           << "0x" << std::setfill('0') << std::setw(kAlignSize)
+           << smap[kStartingAddr] << ","
+           << "0x" << std::setfill('0') << std::setw(kAlignSize)
+           << smap[kEndingAddr] << ",";
+
+    auto pathname = smap[kPathname];
+    if (option & kUseShortPath) {
+      std::size_t found = pathname.rfind('/');
+      if (found != std::string::npos) {
+        pathname = pathname.substr(found + 1);
+      }
+    }
+    output << pathname;
+
+    if (option & kShowFullInfo) {
+      output << "," << smap[kOffset] << "," << smap[kDev] << ","
+             << smap[kInode];
+    }
+    output << "," << smap["Size"] << "," << smap["Rss"] << "," << smap["Pss"]
+           << "," << smap["Swap"] << "," << totalPass;
+    if (option & kShowRegion) {
+      output << "," << smap[kRegion];
+    }
+    output << std::endl;
+  }
+
+  return output.str();
+}
+
+bool dumpMemorySnapshot(std::string outputPath,
+                        std::vector<SmapContents>& smaps) {
+  std::ofstream output(outputPath);
+
+  if (!output) {
+    return false;
+  }
+
+  SnapshotStringOption option =
+      static_cast<SnapshotStringOption>(kUseShortPath | kShowRegion);
+  output << getMemorySnapshotString(smaps, option);
+  return true;
+}
diff --git a/lwnode/code/escargotshim/src/api/utils/smaps.h b/lwnode/code/escargotshim/src/api/utils/smaps.h
new file mode 100644 (file)
index 0000000..a035e4d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @author lwnode-contributors
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+typedef std::unordered_map<std::string, std::string> SmapContents;
+
+constexpr const char* kStartingAddr = "StartingAddr";
+constexpr const char* kEndingAddr = "EndingAddr";
+constexpr const char* kPermissions = "Permissions";
+constexpr const char* kOffset = "Offset";
+constexpr const char* kDev = "Dev";
+constexpr const char* kInode = "Inode";
+constexpr const char* kPathname = "Pathname";
+constexpr const char* kRegion = "Region";
+constexpr const char* kPss = "Pss";
+constexpr const char* kSwap = "Swap";
+
+std::vector<SmapContents> parseSmaps(std::string pid);
+size_t calculateTotal(std::vector<SmapContents>& smaps, const char* key);
+size_t calculateTotalPssSwap(std::vector<SmapContents>& smaps);
+size_t calculateTotalRss(std::vector<SmapContents>& smaps);
+bool dumpMemorySnapshot(std::string outputPath,
+                        std::vector<SmapContents>& smaps);
+
+enum SnapshotStringOption {
+  kShowDefault = 0,
+  kShowFullInfo = 1,
+  kUseShortPath = 1 << 1,
+  kShowRegion = 1 << 2,
+};
+
+std::string getMemorySnapshotString(std::vector<SmapContents>& smaps,
+                                    SnapshotStringOption option = kShowDefault);
+
+bool existsFile(const std::string& path);
+std::string getCurrentTimeString(std::string format = "%y%m%d-%H%M%S");
index ff5f0cc21c322017ff28a96c357caa69d8014c74..846daf46ab5f9c7ec096343fedb438bcfc3e606e 100644 (file)
 
 #include "unimplemented.h"
 
+namespace EscargotShim {
+class ValueWrap;
+}
+
 #define VAL(that) reinterpret_cast<EscargotShim::ValueWrap*>(that)
 #define CVAL(that) reinterpret_cast<const EscargotShim::ValueWrap*>(that)
 
 #define __DLOG_EVAL_EXCEPTION(eval_result)
 #endif
 
-#define API_ENTER(isolate, bailout_value)                                      \
-  LWNODE_CALL_TRACE();                                                         \
+#define __CALL_TRACE_ID(id, ...) LWNODE_CALL_TRACE_ID(id)
+
+#define API_ENTER(isolate, bailout_value, ...)                                 \
+  __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON);                          \
   IsolateWrap* lwIsolate = IsolateWrap::fromV8(isolate);                       \
   __TERMINATION_CHECK(lwIsolate, bailout_value)
 
-#define API_ENTER_NO_EXCEPTION(isolate)                                        \
-  LWNODE_CALL_TRACE();                                                         \
+#define API_ENTER_NO_EXCEPTION(isolate, ...)                                   \
+  __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON);                          \
   IsolateWrap* lwIsolate = IsolateWrap::fromV8(isolate);
 
-#define API_ENTER_WITH_CONTEXT(local_context, bailout_value)                   \
-  LWNODE_CALL_TRACE();                                                         \
+#define API_ENTER_WITH_CONTEXT(local_context, bailout_value, ...)              \
+  __CALL_TRACE_ID(__VA_ARGS__ __VA_OPT__(, ) COMMON);                          \
   IsolateWrap* lwIsolate = local_context.IsEmpty()                             \
                                ? IsolateWrap::GetCurrent()                     \
                                : VAL(*local_context)->context()->GetIsolate(); \
diff --git a/lwnode/code/escargotshim/src/lwnode.cc b/lwnode/code/escargotshim/src/lwnode.cc
new file mode 100644 (file)
index 0000000..3c69a6d
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "lwnode/lwnode.h"
+#include <EscargotPublic.h>
+#include <chrono>
+#include <fstream>
+#include "api.h"
+#include "api/isolate.h"
+#include "api/utils/misc.h"
+#include "api/utils/smaps.h"
+#include "base.h"
+
+using namespace v8;
+using namespace EscargotShim;
+using namespace std::literals;
+
+namespace LWNode {
+
+static void SetMethod(ContextRef* context,
+                      ObjectRef* target,
+                      std::string name,
+                      NativeFunctionPointer nativeFunction) {
+  Evaluator::execute(
+      context,
+      [](ExecutionStateRef* state,
+         ObjectRef* target,
+         StringRef* name,
+         NativeFunctionPointer nativeFunction) -> ValueRef* {
+        target->defineDataProperty(
+            state,
+            name,
+            FunctionObjectRef::create(state,
+                                      FunctionObjectRef::NativeFunctionInfo(
+                                          AtomicStringRef::emptyAtomicString(),
+                                          nativeFunction,
+                                          0,
+                                          true,
+                                          false)),
+            true,
+            true,
+            true);
+
+        return ValueRef::createUndefined();
+      },
+      target,
+      StringRef::createFromASCII(name.c_str(), name.length()),
+      nativeFunction);
+}
+
+constexpr auto kSmapCacheDuration = 600ms;
+
+static std::vector<SmapContents>& getSelfSmaps() {
+  static std::vector<SmapContents> s_cachedSmaps = parseSmaps("self");
+  static auto s_lastUpdatedTime = std::chrono::steady_clock::now();
+
+  if (std::chrono::duration_cast<std::chrono::milliseconds>(
+          std::chrono::steady_clock::now() - s_lastUpdatedTime) <
+      kSmapCacheDuration) {
+    return s_cachedSmaps;
+  }
+
+  s_cachedSmaps = parseSmaps("self");
+  s_lastUpdatedTime = std::chrono::steady_clock::now();
+  return s_cachedSmaps;
+}
+
+static std::string createDumpFilePath() {
+  std::string appName;
+  std::ifstream("/proc/self/comm") >> appName;
+  std::string outputPath =
+      "/tmp/smaps-" + appName + "-" + getCurrentTimeString() + ".csv";
+  return outputPath;
+}
+
+bool dumpSelfMemorySnapshot() {
+  auto& smaps = getSelfSmaps();
+  return dumpMemorySnapshot(createDumpFilePath(), smaps);
+}
+
+static ValueRef* PssUsage(ExecutionStateRef* state,
+                          ValueRef* thisValue,
+                          size_t argc,
+                          ValueRef** argv,
+                          bool isConstructCall) {
+  auto& smaps = getSelfSmaps();
+  size_t total = calculateTotal(smaps, kPss);
+  return ValueRef::create(total);
+};
+
+static ValueRef* PssSwapUsage(ExecutionStateRef* state,
+                              ValueRef* thisValue,
+                              size_t argc,
+                              ValueRef** argv,
+                              bool isConstructCall) {
+  auto& smaps = getSelfSmaps();
+  size_t total = calculateTotalPssSwap(smaps);
+  return ValueRef::create(total);
+};
+
+static ValueRef* RssUsage(ExecutionStateRef* state,
+                          ValueRef* thisValue,
+                          size_t argc,
+                          ValueRef** argv,
+                          bool isConstructCall) {
+  auto& smaps = getSelfSmaps();
+  size_t total = calculateTotalRss(smaps);
+  return ValueRef::create(total);
+};
+
+static ValueRef* MemSnapshot(ExecutionStateRef* state,
+                             ValueRef* thisValue,
+                             size_t argc,
+                             ValueRef** argv,
+                             bool isConstructCall) {
+#ifdef PRODUCTION
+  return ValueRef::create(false);
+#endif
+  auto outputPath = createDumpFilePath();
+  auto& smaps = getSelfSmaps();
+  if (dumpMemorySnapshot(outputPath, smaps)) {
+    return StringRef::createFromASCII(outputPath.c_str(), outputPath.length());
+  }
+  return ValueRef::createUndefined();
+};
+
+void InitializeProcessMethods(Local<Object> target, Local<Context> context) {
+  auto esContext = CVAL(*context)->context()->get();
+  auto esTarget = CVAL(*target)->value()->asObject();
+
+#if !defined(NDEBUG)
+  EvalResultHelper::attachBuiltinPrint(esContext, esTarget);
+#endif
+
+  SetMethod(esContext, esTarget, "PssUsage", PssUsage);
+  SetMethod(esContext, esTarget, "RssUsage", RssUsage);
+  SetMethod(esContext, esTarget, "PssSwapUsage", PssSwapUsage);
+  SetMethod(esContext, esTarget, "MemSnapshot", MemSnapshot);
+}
+
+Utils::ReloadableSourceData* Utils::ReloadableSourceData::create(
+    std::string sourcePath, void* preloadedData, size_t preloadedDataLength) {
+  auto data = new (Memory::gcMalloc(sizeof(ReloadableSourceData)))
+      ReloadableSourceData();
+
+  data->path_ = (char*)Escargot::Memory::gcMalloc(sourcePath.size() + 1);
+  std::copy(sourcePath.begin(), sourcePath.end(), data->path_);
+  data->path_[sourcePath.size()] = '\0';
+
+  data->preloadedData = preloadedData;
+  data->preloadedDataLength_ = preloadedDataLength;
+
+  return data;
+}
+
+MaybeLocal<String> Utils::NewReloadableStringFromOneByte(
+    Isolate* isolate,
+    ReloadableSourceData* data,
+    LoadCallback loadCallback,
+    UnloadCallback unloadCallback) {
+  MaybeLocal<String> result;
+
+  if (data->preloadedDataLength() == 0) {
+    result = String::Empty(isolate);
+  } else if (data->preloadedDataLength() > v8::String::kMaxLength) {
+    result = MaybeLocal<String>();
+  } else {
+    Escargot::StringRef* reloadableString =
+        Escargot::StringRef::createReloadableString(
+            IsolateWrap::fromV8(isolate)->vmInstance(),
+            true,
+            data->preloadedDataLength(),
+            data,  // data should be gc-managed.
+            loadCallback,
+            unloadCallback);
+    result = v8::Utils::NewLocal<String>(isolate, reloadableString);
+  }
+
+  return result;
+}
+
+}  // namespace LWNode
index b50731162bf72ac82d5e67e6db4def465656d92f..9737dc4feaf1af9a4eb95406a9c60ddf5e5ca87d 100644 (file)
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include "api/utils/logger.h"
+#include "api/utils/misc.h"
 
 #define LWNODE_RETURN_VOID                                                     \
   LWNODE_UNIMPLEMENT;                                                          \
index 4808717733a6794436f3296c3f609706ffaf7c29..0de1fb4701bb16e96184f2419e427f6eb06c3086 100644 (file)
--- a/node.gyp
+++ b/node.gyp
         }],
       ],
     }, # fuzz_env
+
     {
       'target_name': 'cctest',
       'type': 'executable',
+      'conditions': [
+        ['lwnode=="true"', {
+          'includes': [ 'lwnode/test/node/cctest.gypi' ],
+        }],
+      ]
+    },  # cctest
+
+    {
+      'target_name': 'cctest8',
+      'type': 'executable',
 
       'dependencies': [
         '<(node_lib_target_name)',
index de9a46a17651acf18fea2c53ce06295ce6868bde..9f2947606f4e3a729b81a453c8fcbdb72719cbd4 100644 (file)
@@ -55,10 +55,8 @@ Requires:    %{name} = %{version}
 Development files for Lightweight node.js.
 
 # Initialize the variables
-%{!?target: %define target lwnode}
-%{!?target_lib: %define target_lib liblwnode}
 %{!?node_engine: %define node_engine escargot}
-%{!?build_profile: %define build_profile none}
+%{!?lib_type: %define lib_type shared}
 
 
 %description
@@ -102,15 +100,30 @@ CXXFLAGS+="-fsanitize=address -fsanitize-recover=address -U_FORTIFY_SOURCE -fno-
 LDFLAGS+="-fsanitize=address"
 %endif
 
+%if "%{node_engine}" == "escargot"
+%define target lwnode
+%define target_lib liblwnode
+%define target_src out/tizen/Release
+%define extra_config --without-bundled-v8 --engine escargot --escargot-threading
+%else
+%define target node
+%define target_src out/v8/Release
+%endif
+
+%if "%{lib_type}" == "shared"
+%define lib_type_config --shared
+%endif
+
 echo "Building:" %{target}
 
-./configure --without-npm --without-bundled-v8 \
+./configure --tizen --without-npm \
             --without-inspector --without-node-code-cache --without-node-snapshot \
             --with-intl none --shared-openssl --shared-zlib --dest-os linux --dest-cpu '%{tizen_arch}' \
-            --engine escargot --ninja --shared
-
-ninja -C out/Release %{target_lib}
-ninja -C out/Release %{target}
+            --ninja %{?extra_config} %{?lib_type_config}
+%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared"
+ninja -C %{target_src} %{target_lib}
+%endif
+ninja -C %{target_src} %{target}
 
 
 ##############################################
@@ -122,15 +135,19 @@ rm -rf %{buildroot}
 mkdir -p %{buildroot}%{_bindir}
 mkdir -p %{buildroot}%{_libdir}
 
-rm -f ./out/Release/lib/*.tmp ./out/Release/lib/*.TOC
-cp ./out/Release/lib/liblwnode.so* %{buildroot}%{_libdir}
-cp ./out/Release/gen/escargot/libescargot.so %{buildroot}%{_libdir}
+rm -f %{target_src}/lib/*.tmp %{target_src}/lib/*.TOC
+%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared"
+cp %{target_src}/lib/liblwnode.so* %{buildroot}%{_libdir}
+cp %{target_src}/gen/escargot/libescargot.so %{buildroot}%{_libdir}
+%endif
 
 # for devel files
-cp ./out/Release/%{target} %{buildroot}%{_bindir}
+strip -v -g %{target_src}/%{target}
+cp %{target_src}/%{target} %{buildroot}%{_bindir}
 
 %clean
 rm ./*.list
+rm ./*.manifest
 
 %post
 /sbin/ldconfig
@@ -146,8 +163,10 @@ rm ./*.list
 %files
 %manifest packaging/%{name}.manifest
 %defattr(-,root,root,-)
+%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared"
 %{_libdir}/libescargot.so
 %{_libdir}/liblwnode.so*
+%endif
 %license LICENSE.Apache-2.0 LICENSE.BOEHM-GC LICENSE.BSD-3-Clause LICENSE.MIT LICENSE.NodeJS
 
 %files devel
index 38e0ef50f9b283b1d7ca8f54412d99b8cd38e524..4f72c7701a70010d95a988b030e434f84ad5a74e 100644 (file)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-function-type"
 #endif
+
+#ifdef LWNODE
+#include "lwnode.h"
+#include "trace.h"
+#endif
+
 #include "v8.h"  // NOLINT(build/include_order)
 #if (__GNUC__ >= 8) && !defined(__clang__)
 #pragma GCC diagnostic pop
index 797ba3db03be87dd22ef5d00f05274dc61b71041..9f97bf1462b94427d453dd636e804bfedd891282 100644 (file)
@@ -430,7 +430,9 @@ void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate,
 void NodePlatform::Shutdown() {
   if (has_shut_down_) return;
   has_shut_down_ = true;
-  worker_thread_task_runner_->Shutdown();
+  if (worker_thread_task_runner_) { // @lwnode
+    worker_thread_task_runner_->Shutdown();
+  }
 
   {
     Mutex::ScopedLock lock(per_isolate_mutex_);
@@ -477,6 +479,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
 void NodePlatform::DrainTasks(Isolate* isolate) {
   std::shared_ptr<PerIsolatePlatformData> per_isolate = ForNodeIsolate(isolate);
   if (!per_isolate) return;
+  if (!worker_thread_task_runner_) return; // @lwnode
 
   do {
     // Worker tasks aren't associated with an Isolate.
index 8c8a209b3ec1512d9a64c797f5197b3a3a33a815..de6561cef7b30eebd81175ffdbabe227c07ca37c 100644 (file)
@@ -463,6 +463,9 @@ static void InitializeProcessMethods(Local<Object> target,
   env->SetMethod(target, "reallyExit", ReallyExit);
   env->SetMethodNoSideEffect(target, "uptime", Uptime);
   env->SetMethod(target, "patchProcessObject", PatchProcessObject);
+#ifdef LWNODE
+  LWNode::InitializeProcessMethods(target, context);
+#endif
 }
 
 }  // namespace node
index 2e018c4177cd2e3fa82d21336e5ab882a0054221..8584b45d31fcaedb5746d89e31c18ee47c3fbed2 100644 (file)
@@ -24,11 +24,14 @@ using v8::FunctionTemplate;
 using v8::HandleScope;
 using v8::Integer;
 using v8::Isolate;
+using v8::Just;
 using v8::Local;
 using v8::Locker;
+using v8::Maybe;
 using v8::MaybeLocal;
 using v8::Null;
 using v8::Number;
+using v8::Nothing;
 using v8::Object;
 using v8::ResourceConstraints;
 using v8::SealHandleScope;
@@ -364,6 +367,7 @@ void Worker::Run() {
     }
 
     {
+      /*
       int exit_code;
       bool stopped = is_stopped();
       if (!stopped)
@@ -371,9 +375,22 @@ void Worker::Run() {
       Mutex::ScopedLock lock(mutex_);
       if (exit_code_ == 0 && !stopped)
         exit_code_ = exit_code;
+      */
+      // @lwnode remove warning: ‘exit_code’ may be used uninitialized
+      Maybe<int> exit_code = Nothing<int>();
+      bool stopped = is_stopped();
+      if (!stopped) {
+        exit_code = Just<int>(EmitExit(env_.get()));
+      }
+      Mutex::ScopedLock lock(mutex_);
+      if (exit_code_ == 0 && !stopped && exit_code.IsJust()) {
+        exit_code_ = exit_code.FromJust();
+      }
 
-      Debug(this, "Exiting thread for worker %llu with exit code %d",
-            thread_id_.id, exit_code_);
+      Debug(this,
+            "Exiting thread for worker %llu with exit code %d",
+            thread_id_.id,
+            exit_code_);
     }
   }
 
index 332a72949f7ad313a4e8b1d92b39bb068b80a832..9b0ced3099c7f73b4c61b4c39b0243ea7f692032 100755 (executable)
@@ -35,8 +35,17 @@ def run_gyp(args):
   args.append('--depth=' + node_root)
 
 # @lwnode
-  if '-Dnode_core_target_name=lwnode' not in args:
-    global output_dir
+  global output_dir
+  if '-Dnode_core_target_name=lwnode' in args:
+    if '-Dtarget_os=tizen' in args:
+      output_dir = os.path.join(output_dir, 'tizen')
+      args.extend(['--generator-output', output_dir])
+      args.extend(['-Goutput_dir=' + output_dir])
+    else:
+      output_dir = os.path.join(output_dir, 'linux')
+      args.extend(['--generator-output', output_dir])
+      args.extend(['-Goutput_dir=' + output_dir])
+  else:
     output_dir = os.path.join(output_dir, 'v8')
     args.extend(['--generator-output', output_dir])
     args.extend(['-Goutput_dir=' + output_dir])
index 4d97a5bb26983a41c20159beb6f2720a841f649b..c55b0a9b8930c7bd6e77f26c90f0e8b690bc44f8 100755 (executable)
@@ -908,7 +908,7 @@ class Context(object):
     if self.vm is not None:
       return self.vm
     if arch == 'none':
-      name = 'out/Debug/lwnode' if mode == 'debug' else 'out/Release/lwnode'
+      name = 'out/linux/Debug/lwnode' if mode == 'debug' else 'out/linux/Release/lwnode'
     else:
       name = 'out/%s.%s/lwnode' % (arch, mode)