WebAssemblyInstance.cpp 20 KB

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