WebAssemblyInstance.cpp 21 KB

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