WebAssemblyInstance.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLibraryPch.h"
  6. #ifdef ENABLE_WASM
  7. #include "../WasmReader/WasmReaderPch.h"
  8. namespace Js
  9. {
  10. Var GetImportVariable(Wasm::WasmImport* wi, ScriptContext* ctx, Var ffi)
  11. {
  12. PropertyRecord const * modPropertyRecord = nullptr;
  13. const char16* modName = wi->modName;
  14. uint32 modNameLen = wi->modNameLen;
  15. ctx->GetOrAddPropertyRecord(modName, modNameLen, &modPropertyRecord);
  16. Var modProp = JavascriptOperators::OP_GetProperty(ffi, modPropertyRecord->GetPropertyId(), ctx);
  17. const char16* name = wi->importName;
  18. uint32 nameLen = wi->importNameLen;
  19. PropertyRecord const * propertyRecord = nullptr;
  20. ctx->GetOrAddPropertyRecord(name, nameLen, &propertyRecord);
  21. if (!RecyclableObject::Is(modProp))
  22. {
  23. JavascriptError::ThrowTypeError(ctx, WASMERR_InvalidImport);
  24. }
  25. return JavascriptOperators::OP_GetProperty(modProp, propertyRecord->GetPropertyId(), ctx);
  26. }
  27. WebAssemblyInstance::WebAssemblyInstance(WebAssemblyModule * wasmModule, DynamicType * type) :
  28. DynamicObject(type),
  29. m_module(wasmModule),
  30. m_exports(nullptr)
  31. {
  32. }
  33. /* static */
  34. bool
  35. WebAssemblyInstance::Is(Var value)
  36. {
  37. return JavascriptOperators::GetTypeId(value) == TypeIds_WebAssemblyInstance;
  38. }
  39. /* static */
  40. WebAssemblyInstance *
  41. WebAssemblyInstance::FromVar(Var value)
  42. {
  43. Assert(WebAssemblyInstance::Is(value));
  44. return static_cast<WebAssemblyInstance*>(value);
  45. }
  46. // Implements "new WebAssembly.Instance(moduleObject [, importObject])" as described here:
  47. // https://github.com/WebAssembly/design/blob/master/JS.md#webassemblyinstance-constructor
  48. Var
  49. WebAssemblyInstance::NewInstance(RecyclableObject* function, CallInfo callInfo, ...)
  50. {
  51. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  52. ARGUMENTS(args, callInfo);
  53. ScriptContext* scriptContext = function->GetScriptContext();
  54. AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
  55. Var newTarget = callInfo.Flags & CallFlags_NewTarget ? args.Values[args.Info.Count] : args[0];
  56. bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && newTarget != nullptr && !JavascriptOperators::IsUndefined(newTarget);
  57. Assert(isCtorSuperCall || !(callInfo.Flags & CallFlags_New) || args[0] == nullptr);
  58. if (!(callInfo.Flags & CallFlags_New) || (newTarget && JavascriptOperators::IsUndefinedObject(newTarget)))
  59. {
  60. JavascriptError::ThrowTypeError(scriptContext, JSERR_ClassConstructorCannotBeCalledWithoutNew, _u("WebAssembly.Instance"));
  61. }
  62. if (args.Info.Count < 2 || !WebAssemblyModule::Is(args[1]))
  63. {
  64. JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedModule);
  65. }
  66. WebAssemblyModule * module = WebAssemblyModule::FromVar(args[1]);
  67. Var importObject = scriptContext->GetLibrary()->GetUndefined();
  68. if (args.Info.Count >= 3)
  69. {
  70. importObject = args[2];
  71. }
  72. return CreateInstance(module, importObject);
  73. }
  74. Var
  75. WebAssemblyInstance::GetterExports(RecyclableObject* function, CallInfo callInfo, ...)
  76. {
  77. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  78. ARGUMENTS(args, callInfo);
  79. ScriptContext* scriptContext = function->GetScriptContext();
  80. Assert(!(callInfo.Flags & CallFlags_New));
  81. if (args.Info.Count == 0 || !WebAssemblyInstance::Is(args[0]))
  82. {
  83. JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedInstanceObject);
  84. }
  85. WebAssemblyInstance* instance = WebAssemblyInstance::FromVar(args[0]);
  86. Js::Var exports = instance->m_exports;
  87. if (!exports || !DynamicObject::Is(exports))
  88. {
  89. Assert(UNREACHED);
  90. exports = scriptContext->GetLibrary()->GetUndefined();
  91. }
  92. return exports;
  93. }
  94. WebAssemblyInstance *
  95. WebAssemblyInstance::CreateInstance(WebAssemblyModule * module, Var importObject)
  96. {
  97. if (!JavascriptOperators::IsUndefined(importObject) && !JavascriptOperators::IsObject(importObject))
  98. {
  99. JavascriptError::ThrowTypeError(module->GetScriptContext(), JSERR_NeedObject);
  100. }
  101. if (module->GetImportCount() > 0 && !JavascriptOperators::IsObject(importObject))
  102. {
  103. JavascriptError::ThrowTypeError(module->GetScriptContext(), JSERR_NeedObject);
  104. }
  105. ScriptContext * scriptContext = module->GetScriptContext();
  106. WebAssemblyEnvironment environment(module);
  107. WebAssemblyInstance * newInstance = RecyclerNewZ(scriptContext->GetRecycler(), WebAssemblyInstance, module, scriptContext->GetLibrary()->GetWebAssemblyInstanceType());
  108. try
  109. {
  110. LoadImports(module, scriptContext, importObject, &environment);
  111. LoadGlobals(module, scriptContext, &environment);
  112. LoadFunctions(module, scriptContext, &environment);
  113. ValidateTableAndMemory(module, scriptContext, &environment);
  114. try
  115. {
  116. LoadDataSegs(module, scriptContext, &environment);
  117. LoadIndirectFunctionTable(module, scriptContext, &environment);
  118. }
  119. catch (...)
  120. {
  121. AssertMsg(UNREACHED, "By spec, we should not have any exceptions possible here");
  122. throw;
  123. }
  124. newInstance->m_exports = BuildObject(module, scriptContext, &environment);
  125. }
  126. catch (Wasm::WasmCompilationException& e)
  127. {
  128. JavascriptError::ThrowWebAssemblyLinkErrorVar(scriptContext, WASMERR_WasmLinkError, e.GetTempErrorMessageRef());
  129. }
  130. uint32 startFuncIdx = module->GetStartFunction();
  131. if (startFuncIdx != Js::Constants::UninitializedValue)
  132. {
  133. AsmJsScriptFunction* start = environment.GetWasmFunction(startFuncIdx);
  134. Js::CallInfo info(Js::CallFlags_New, 1);
  135. Js::Arguments startArg(info, (Var*)&start);
  136. Js::JavascriptFunction::CallFunction<true>(start, start->GetEntryPoint(), startArg);
  137. }
  138. return newInstance;
  139. }
  140. void WebAssemblyInstance::LoadFunctions(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment* env)
  141. {
  142. FrameDisplay * frameDisplay = RecyclerNewPlus(ctx->GetRecycler(), sizeof(void*), FrameDisplay, 1);
  143. frameDisplay->SetItem(0, env->GetStartPtr());
  144. for (uint i = 0; i < wasmModule->GetWasmFunctionCount(); ++i)
  145. {
  146. if (i < wasmModule->GetImportedFunctionCount() && env->GetWasmFunction(i) != nullptr)
  147. {
  148. continue;
  149. }
  150. Wasm::WasmFunctionInfo* wasmFuncInfo = wasmModule->GetWasmFunctionInfo(i);
  151. FunctionBody* body = wasmFuncInfo->GetBody();
  152. AsmJsScriptFunction * funcObj = ctx->GetLibrary()->CreateAsmJsScriptFunction(body);
  153. funcObj->SetModuleMemory((Field(Var)*)env->GetStartPtr());
  154. funcObj->SetSignature(body->GetAsmJsFunctionInfo()->GetWasmSignature());
  155. funcObj->SetEnvironment(frameDisplay);
  156. // Todo:: need to fix issue #2452 before we can do this,
  157. // otherwise we'll change the type of the functions and cause multiple instance to not share jitted code
  158. //Wasm::WasmSignature* sig = wasmFuncInfo->GetSignature();
  159. //funcObj->SetPropertyWithAttributes(PropertyIds::length, JavascriptNumber::ToVar(sig->GetParamCount(), ctx), PropertyNone, nullptr);
  160. //funcObj->SetPropertyWithAttributes(PropertyIds::name, JavascriptConversion::ToString(JavascriptNumber::ToVar(i, ctx), ctx), PropertyNone, nullptr);
  161. env->SetWasmFunction(i, funcObj);
  162. if (!PHASE_OFF(WasmDeferredPhase, body))
  163. {
  164. // if we still have WasmReaderInfo we haven't yet parsed
  165. if (body->GetAsmJsFunctionInfo()->GetWasmReaderInfo())
  166. {
  167. WasmLibrary::SetWasmEntryPointToInterpreter(funcObj, true);
  168. }
  169. }
  170. else
  171. {
  172. AsmJsFunctionInfo* info = body->GetAsmJsFunctionInfo();
  173. if (info->GetWasmReaderInfo())
  174. {
  175. WasmLibrary::SetWasmEntryPointToInterpreter(funcObj, false);
  176. WAsmJs::JitFunctionIfReady(funcObj);
  177. info->SetWasmReaderInfo(nullptr);
  178. }
  179. }
  180. }
  181. }
  182. void WebAssemblyInstance::LoadDataSegs(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment* env)
  183. {
  184. WebAssemblyMemory* mem = env->GetMemory(0);
  185. Assert(mem);
  186. ArrayBuffer* buffer = mem->GetBuffer();
  187. for (uint32 iSeg = 0; iSeg < wasmModule->GetDataSegCount(); ++iSeg)
  188. {
  189. Wasm::WasmDataSegment* segment = wasmModule->GetDataSeg(iSeg);
  190. Assert(segment != nullptr);
  191. const uint32 offset = env->GetDataSegmentOffset(iSeg);
  192. const uint32 size = segment->GetSourceSize();
  193. if (size > 0)
  194. {
  195. js_memcpy_s(buffer->GetBuffer() + offset, (uint32)buffer->GetByteLength() - offset, segment->GetData(), size);
  196. }
  197. }
  198. }
  199. Var WebAssemblyInstance::BuildObject(WebAssemblyModule * wasmModule, ScriptContext* scriptContext, WebAssemblyEnvironment* env)
  200. {
  201. Js::Var exportsNamespace = scriptContext->GetLibrary()->CreateObject(scriptContext->GetLibrary()->GetNull());
  202. for (uint32 iExport = 0; iExport < wasmModule->GetExportCount(); ++iExport)
  203. {
  204. Wasm::WasmExport* wasmExport = wasmModule->GetExport(iExport);
  205. Assert(wasmExport);
  206. if (wasmExport)
  207. {
  208. PropertyRecord const * propertyRecord = nullptr;
  209. scriptContext->GetOrAddPropertyRecord(wasmExport->name, wasmExport->nameLength, &propertyRecord);
  210. Var obj = scriptContext->GetLibrary()->GetUndefined();
  211. switch (wasmExport->kind)
  212. {
  213. case Wasm::ExternalKinds::Table:
  214. obj = env->GetTable(wasmExport->index);
  215. break;
  216. case Wasm::ExternalKinds::Memory:
  217. obj = env->GetMemory(wasmExport->index);
  218. break;
  219. case Wasm::ExternalKinds::Function:
  220. obj = env->GetWasmFunction(wasmExport->index);
  221. break;
  222. case Wasm::ExternalKinds::Global:
  223. Wasm::WasmGlobal* global = wasmModule->GetGlobal(wasmExport->index);
  224. if (global->IsMutable())
  225. {
  226. JavascriptError::ThrowTypeError(wasmModule->GetScriptContext(), WASMERR_MutableGlobal);
  227. }
  228. Wasm::WasmConstLitNode cnst = env->GetGlobalValue(global);
  229. switch (global->GetType())
  230. {
  231. case Wasm::WasmTypes::I32:
  232. obj = JavascriptNumber::ToVar(cnst.i32, scriptContext);
  233. break;
  234. case Wasm::WasmTypes::F32:
  235. obj = JavascriptNumber::New(cnst.f32, scriptContext);
  236. break;
  237. case Wasm::WasmTypes::F64:
  238. obj = JavascriptNumber::New(cnst.f64, scriptContext);
  239. break;
  240. case Wasm::WasmTypes::I64:
  241. JavascriptError::ThrowTypeError(wasmModule->GetScriptContext(), WASMERR_InvalidTypeConversion);
  242. default:
  243. Assert(UNREACHED);
  244. break;
  245. }
  246. }
  247. JavascriptOperators::OP_SetProperty(exportsNamespace, propertyRecord->GetPropertyId(), obj, scriptContext);
  248. }
  249. }
  250. DynamicObject::FromVar(exportsNamespace)->PreventExtensions();
  251. return exportsNamespace;
  252. }
  253. void WebAssemblyInstance::LoadImports(
  254. WebAssemblyModule * wasmModule,
  255. ScriptContext* ctx,
  256. Var ffi,
  257. WebAssemblyEnvironment* env)
  258. {
  259. const uint32 importCount = wasmModule->GetImportCount();
  260. if (importCount > 0 && (!ffi || !RecyclableObject::Is(ffi)))
  261. {
  262. JavascriptError::ThrowTypeError(ctx, WASMERR_InvalidImport);
  263. }
  264. uint32 counters[Wasm::ExternalKinds::Limit];
  265. memset(counters, 0, sizeof(counters));
  266. for (uint32 i = 0; i < importCount; ++i)
  267. {
  268. Wasm::WasmImport* import = wasmModule->GetImport(i);
  269. Var prop = GetImportVariable(import, ctx, ffi);
  270. uint32& counter = counters[import->kind];
  271. switch (import->kind)
  272. {
  273. case Wasm::ExternalKinds::Function:
  274. {
  275. if (!JavascriptFunction::Is(prop))
  276. {
  277. JavascriptError::ThrowWebAssemblyLinkError(ctx, JSERR_Property_NeedFunction);
  278. }
  279. Assert(counter < wasmModule->GetImportedFunctionCount());
  280. Assert(wasmModule->GetFunctionIndexType(counter) == Wasm::FunctionIndexTypes::ImportThunk);
  281. env->SetImportedFunction(counter, prop);
  282. if (AsmJsScriptFunction::IsWasmScriptFunction(prop))
  283. {
  284. Assert(env->GetWasmFunction(counter) == nullptr);
  285. AsmJsScriptFunction* func = AsmJsScriptFunction::FromVar(prop);
  286. if (!wasmModule->GetWasmFunctionInfo(counter)->GetSignature()->IsEquivalent(func->GetSignature()))
  287. {
  288. char16 temp[2048] = { 0 };
  289. char16 importargs[512] = { 0 };
  290. wasmModule->GetWasmFunctionInfo(counter)->GetSignature()->WriteSignatureToString(importargs, 512);
  291. char16 exportargs[512] = { 0 };
  292. func->GetSignature()->WriteSignatureToString(exportargs, 512);
  293. _snwprintf_s(temp, 2048, _TRUNCATE, _u("%ls%ls to %ls%ls"), func->GetDisplayName()->GetString(), exportargs, import->importName, importargs);
  294. // this makes a copy of the error message buffer, so it's fine to not worry about clean-up
  295. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_LinkSignatureMismatch, temp);
  296. }
  297. // Imported Wasm functions can be called directly
  298. env->SetWasmFunction(counter, func);
  299. }
  300. break;
  301. }
  302. case Wasm::ExternalKinds::Memory:
  303. {
  304. Assert(wasmModule->HasMemoryImport());
  305. if (wasmModule->HasMemoryImport())
  306. {
  307. if (!WebAssemblyMemory::Is(prop))
  308. {
  309. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_NeedMemoryObject);
  310. }
  311. WebAssemblyMemory * mem = WebAssemblyMemory::FromVar(prop);
  312. if (mem->GetInitialLength() < wasmModule->GetMemoryInitSize())
  313. {
  314. throw Wasm::WasmCompilationException(_u("Imported memory initial size (%u) is smaller than declared (%u)"), mem->GetInitialLength(), wasmModule->GetMemoryInitSize());
  315. }
  316. if (mem->GetMaximumLength() > wasmModule->GetMemoryMaxSize())
  317. {
  318. throw Wasm::WasmCompilationException(_u("Imported memory maximum size (%u) is larger than declared (%u)"), mem->GetMaximumLength(), wasmModule->GetMemoryMaxSize());
  319. }
  320. env->SetMemory(counter, mem);
  321. }
  322. break;
  323. }
  324. case Wasm::ExternalKinds::Table:
  325. {
  326. Assert(wasmModule->HasTableImport());
  327. if (wasmModule->HasTableImport())
  328. {
  329. if (!WebAssemblyTable::Is(prop))
  330. {
  331. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_NeedTableObject);
  332. }
  333. WebAssemblyTable * table = WebAssemblyTable::FromVar(prop);
  334. if (!wasmModule->IsValidTableImport(table))
  335. {
  336. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_NeedTableObject);
  337. }
  338. env->SetTable(counter, table);
  339. }
  340. break;
  341. }
  342. case Wasm::ExternalKinds::Global:
  343. {
  344. Wasm::WasmGlobal* global = wasmModule->GetGlobal(counter);
  345. if (global->IsMutable() || (!JavascriptNumber::Is(prop) && !TaggedInt::Is(prop)))
  346. {
  347. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_InvalidImport);
  348. }
  349. Assert(global->GetReferenceType() == Wasm::GlobalReferenceTypes::ImportedReference);
  350. Wasm::WasmConstLitNode cnst = {0};
  351. switch (global->GetType())
  352. {
  353. case Wasm::WasmTypes::I32: cnst.i32 = JavascriptConversion::ToInt32(prop, ctx); break;
  354. case Wasm::WasmTypes::F32: cnst.f32 = (float)JavascriptConversion::ToNumber(prop, ctx); break;
  355. case Wasm::WasmTypes::F64: cnst.f64 = JavascriptConversion::ToNumber(prop, ctx); break;
  356. case Wasm::WasmTypes::I64: Js::JavascriptError::ThrowTypeError(ctx, WASMERR_InvalidTypeConversion);
  357. default:
  358. Js::Throw::InternalError();
  359. }
  360. env->SetGlobalValue(global, cnst);
  361. break;
  362. }
  363. default:
  364. Js::Throw::InternalError();
  365. }
  366. ++counter;
  367. }
  368. }
  369. void WebAssemblyInstance::LoadGlobals(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment* env)
  370. {
  371. uint count = wasmModule->GetGlobalCount();
  372. for (uint i = 0; i < count; i++)
  373. {
  374. Wasm::WasmGlobal* global = wasmModule->GetGlobal(i);
  375. Wasm::WasmConstLitNode cnst = {};
  376. if (global->GetReferenceType() == Wasm::GlobalReferenceTypes::ImportedReference)
  377. {
  378. // the value should already be resolved
  379. continue;
  380. }
  381. if (global->GetReferenceType() == Wasm::GlobalReferenceTypes::LocalReference)
  382. {
  383. Wasm::WasmGlobal* sourceGlobal = wasmModule->GetGlobal(global->GetGlobalIndexInit());
  384. if (sourceGlobal->GetReferenceType() != Wasm::GlobalReferenceTypes::Const &&
  385. sourceGlobal->GetReferenceType() != Wasm::GlobalReferenceTypes::ImportedReference)
  386. {
  387. JavascriptError::ThrowTypeError(ctx, WASMERR_InvalidGlobalRef);
  388. }
  389. if (sourceGlobal->GetType() != global->GetType())
  390. {
  391. JavascriptError::ThrowTypeError(ctx, WASMERR_InvalidTypeConversion);
  392. }
  393. cnst = env->GetGlobalValue(sourceGlobal);
  394. }
  395. else
  396. {
  397. cnst = global->GetConstInit();
  398. }
  399. env->SetGlobalValue(global, cnst);
  400. }
  401. }
  402. void WebAssemblyInstance::LoadIndirectFunctionTable(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment* env)
  403. {
  404. WebAssemblyTable* table = env->GetTable(0);
  405. Assert(table != nullptr);
  406. for (uint elementsIndex = 0; elementsIndex < wasmModule->GetElementSegCount(); ++elementsIndex)
  407. {
  408. Wasm::WasmElementSegment* eSeg = wasmModule->GetElementSeg(elementsIndex);
  409. if (eSeg->GetNumElements() > 0)
  410. {
  411. uint offset = env->GetElementSegmentOffset(elementsIndex);
  412. for (uint segIndex = 0; segIndex < eSeg->GetNumElements(); ++segIndex)
  413. {
  414. uint funcIndex = eSeg->GetElement(segIndex);
  415. Var funcObj = env->GetWasmFunction(funcIndex);
  416. table->DirectSetValue(segIndex + offset, funcObj);
  417. }
  418. }
  419. }
  420. }
  421. void WebAssemblyInstance::ValidateTableAndMemory(WebAssemblyModule * wasmModule, ScriptContext* ctx, WebAssemblyEnvironment* env)
  422. {
  423. WebAssemblyTable* table = env->GetTable(0);
  424. if (wasmModule->HasTableImport())
  425. {
  426. if (table == nullptr)
  427. {
  428. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_NeedTableObject);
  429. }
  430. }
  431. else
  432. {
  433. table = wasmModule->CreateTable();
  434. env->SetTable(0, table);
  435. }
  436. WebAssemblyMemory* mem = env->GetMemory(0);
  437. if (wasmModule->HasMemoryImport())
  438. {
  439. if (mem == nullptr)
  440. {
  441. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_NeedMemoryObject);
  442. }
  443. }
  444. else
  445. {
  446. mem = wasmModule->CreateMemory();
  447. if (mem == nullptr)
  448. {
  449. JavascriptError::ThrowWebAssemblyLinkError(ctx, WASMERR_MemoryCreateFailed);
  450. }
  451. env->SetMemory(0, mem);
  452. }
  453. ArrayBuffer * buffer = mem->GetBuffer();
  454. if (buffer->IsDetached())
  455. {
  456. JavascriptError::ThrowTypeError(wasmModule->GetScriptContext(), JSERR_DetachedTypedArray);
  457. }
  458. env->CalculateOffsets(table, mem);
  459. }
  460. } // namespace Js
  461. #endif // ENABLE_WASM