From 7609106ced1729267ad26455d7bc55d94a2f024b Mon Sep 17 00:00:00 2001 From: Dan Lapid Date: Thu, 17 Oct 2024 15:59:29 +0000 Subject: [PATCH] broken --- src/pyodide/BUILD.bazel | 36 ++++ src/pyodide/internal/pool/builtin_wrappers.ts | 12 +- src/pyodide/internal/pool/emscriptenSetup.ts | 26 ++- src/pyodide/internal/python.ts | 52 +----- src/pyodide/pyodide_extra.capnp | 6 +- src/pyodide/python-entrypoint-helper.ts | 3 +- src/pyodide/types/emscripten.d.ts | 4 + src/workerd/api/BUILD.bazel | 7 + src/workerd/api/modules.h | 3 + src/workerd/api/pyodide/setup-emscripten.c++ | 156 ++++++++++++++++++ src/workerd/api/pyodide/setup-emscripten.h | 59 +++++++ src/workerd/jsg/modules.c++ | 8 + src/workerd/jsg/setup.c++ | 1 + src/workerd/server/workerd-api.c++ | 17 +- 14 files changed, 331 insertions(+), 59 deletions(-) create mode 100644 src/workerd/api/pyodide/setup-emscripten.c++ create mode 100644 src/workerd/api/pyodide/setup-emscripten.h diff --git a/src/pyodide/BUILD.bazel b/src/pyodide/BUILD.bazel index bed4ebe42ab..ca3057620a5 100644 --- a/src/pyodide/BUILD.bazel +++ b/src/pyodide/BUILD.bazel @@ -295,3 +295,39 @@ genrule( tools = ["@capnp-cpp//src/capnp:capnp_tool"], visibility = ["//visibility:public"], ) + +capnp_embed( + name = "emscripten_setup_capnp_file_embed", + src = "generated/emscripten_setup.capnp", + deps = ["emscripten_setup_capnp_file"], +) + +capnp_embed( + name = "emscripten_setup_js_file_embed", + src = "generated/emscriptenSetup.js", + deps = ["generated/emscriptenSetup"], +) + +capnp_embed( + name = "python_stdlib_zip_file_embed", + src = "generated/python_stdlib.zip", + deps = ["python_stdlib.zip@rule"], +) + +capnp_embed( + name = "pyodide_asm_wasm_file_embed", + src = "generated/pyodide.asm.wasm", + deps = ["pyodide.asm.wasm@rule"], +) + +cc_capnp_library( + name = "emscripten_setup_capnp", + srcs = ["generated/emscripten_setup.capnp"], + visibility = ["//visibility:public"], + deps = [ + ":emscripten_setup_capnp_file_embed", + ":emscripten_setup_js_file_embed", + ":pyodide_asm_wasm_file_embed", + ":python_stdlib_zip_file_embed", + ], +) diff --git a/src/pyodide/internal/pool/builtin_wrappers.ts b/src/pyodide/internal/pool/builtin_wrappers.ts index 8743567051a..18080a993af 100644 --- a/src/pyodide/internal/pool/builtin_wrappers.ts +++ b/src/pyodide/internal/pool/builtin_wrappers.ts @@ -1,11 +1,21 @@ import type { getRandomValues as getRandomValuesType } from 'pyodide-internal:topLevelEntropy/lib'; +import type { default as UnsafeEvalType } from 'internal:unsafe-eval'; +let getRandomValuesInner: typeof getRandomValuesType; +export function setGetRandomValues(func: typeof getRandomValuesType) { + getRandomValuesInner = func; +} export function getRandomValues(Module: Module, arr: Uint8Array): Uint8Array { return getRandomValuesInner(Module, arr); } - +// We can't import UnsafeEval directly here because it isn't available when setting up Python pool. +// Thus, we inject it from outside via this function. +let UnsafeEval: typeof UnsafeEvalType; +export function setUnsafeEval(mod: typeof UnsafeEvalType) { + UnsafeEval = mod; +} let lastTime: number; let lastDelta = 0; /** diff --git a/src/pyodide/internal/pool/emscriptenSetup.ts b/src/pyodide/internal/pool/emscriptenSetup.ts index fcf5bff1f47..d0f661695fc 100644 --- a/src/pyodide/internal/pool/emscriptenSetup.ts +++ b/src/pyodide/internal/pool/emscriptenSetup.ts @@ -7,17 +7,17 @@ import { reportError } from 'pyodide-internal:util'; +import { + setUnsafeEval, + setGetRandomValues, +} from 'pyodide-internal:pool/builtin_wrappers'; + /** * _createPyodideModule and pyodideWasmModule together are produced by the * Emscripten linker */ import { _createPyodideModule } from 'pyodide-internal:generated/pyodide.asm'; -export { - setUnsafeEval, - setGetRandomValues, -} from 'pyodide-internal:pool/builtin_wrappers'; - /** * A preRun hook. Make sure environment variables are visible at runtime. */ @@ -56,7 +56,7 @@ function getWaitForDynlibs(resolveReadyPromise: PreRunHook): PreRunHook { * This is a simplified version of the `prepareFileSystem` function here: * https://github.com/pyodide/pyodide/blob/main/src/js/module.ts */ -function getPrepareFileSystem(pythonStdlib: Uint8Array): PreRunHook { +function getPrepareFileSystem(pythonStdlib: ArrayBuffer): PreRunHook { return function prepareFileSystem(Module: Module): void { try { const pymajor = Module._py_version_major(); @@ -99,11 +99,13 @@ function getInstantiateWasm( ) => void ): WebAssembly.Exports { (async function () { + console.log('instantiateWasm1'); // Instantiate pyodideWasmModule with wasmImports const instance = await WebAssembly.instantiate( pyodideWasmModule, wasmImports ); + console.log('instantiateWasm1'); successCallback(instance, pyodideWasmModule); })(); @@ -118,7 +120,7 @@ function getInstantiateWasm( */ function getEmscriptenSettings( isWorkerd: boolean, - pythonStdlib: Uint8Array, + pythonStdlib: ArrayBuffer, pyodideWasmModule: WebAssembly.Module ): EmscriptenSettings { const config: PyodideConfig = { @@ -193,9 +195,10 @@ function* featureDetectionMonkeyPatchesContextManager() { */ export async function instantiateEmscriptenModule( isWorkerd: boolean, - pythonStdlib: Uint8Array, + pythonStdlib: ArrayBuffer, wasmModule: WebAssembly.Module ): Promise { + console.log('instantiateEmscriptenModule js 1'); const emscriptenSettings = getEmscriptenSettings( isWorkerd, pythonStdlib, @@ -203,14 +206,19 @@ export async function instantiateEmscriptenModule( ); try { for (const _ of featureDetectionMonkeyPatchesContextManager()) { + console.log('instantiateEmscriptenModule js 4'); // Ignore the returned promise, it won't resolve until we're done preloading dynamic // libraries. const _promise = _createPyodideModule(emscriptenSettings); } + console.log('instantiateEmscriptenModule js 5'); // Wait until we've executed all the preRun hooks before proceeding const emscriptenModule = await emscriptenSettings.readyPromise; - ems + console.log('instantiateEmscriptenModule js 6'); + emscriptenModule.setUnsafeEval = setUnsafeEval; + emscriptenModule.setGetRandomValues = setGetRandomValues; + console.log('instantiateEmscriptenModule js 7'); return emscriptenModule; } catch (e) { console.warn('Error in instantiateEmscriptenModule'); diff --git a/src/pyodide/internal/python.ts b/src/pyodide/internal/python.ts index 53db0b8871f..c7540cf2f2e 100644 --- a/src/pyodide/internal/python.ts +++ b/src/pyodide/internal/python.ts @@ -20,49 +20,8 @@ import { } from 'pyodide-internal:topLevelEntropy/lib'; import { default as SetupEmscripten } from 'internal:setup-emscripten'; -// import { default as UnsafeEval } from 'internal:unsafe-eval'; +import { default as UnsafeEval } from 'internal:unsafe-eval'; -// /** -// * This file is a simplified version of the Pyodide loader: -// * https://github.com/pyodide/pyodide/blob/main/src/js/pyodide.ts -// * -// * In particular, it drops the package lock, which disables -// * `pyodide.loadPackage`. In trade we add memory snapshots here. -// */ - -// /** -// * _createPyodideModule and pyodideWasmModule together are produced by the -// * Emscripten linker -// */ -// import pyodideWasmModule from 'pyodide-internal:generated/pyodide.asm.wasm'; - -// /** -// * The Python and Pyodide stdlib zipped together. The zip format is convenient -// * because Python has a "ziploader" that allows one to import directly from a -// * zip file. -// * -// * The ziploader solves bootstrapping problems around unpacking: Python comes -// * with a bunch of C libs to unpack various archive formats, but they need stuff -// * in this zip file to initialize their runtime state. -// */ -// import pythonStdlib from 'pyodide-internal:generated/python_stdlib.zip'; -import { - instantiateEmscriptenModule, - setUnsafeEval, - setGetRandomValues, -} from 'pyodide-internal:generated/emscriptenSetup'; - -// We can't import UnsafeEval directly here because it isn't available when setting up Python pool. -// Thus, we inject it from outside via this function. -let UnsafeEval: typeof UnsafeEvalType; -function setUnsafeEval(mod: typeof UnsafeEvalType) { - UnsafeEval = mod; -} - -let getRandomValuesInner: typeof getRandomValuesType; -function setGetRandomValues(func: typeof getRandomValuesType) { - getRandomValuesInner = func; -} /** * After running `instantiateEmscriptenModule` but before calling into any C * APIs, we call this function. If `MEMORY` is defined, then we will have passed @@ -95,13 +54,18 @@ export async function loadPyodide( lockfile: PackageLock, indexURL: string ): Promise { + console.log('getting module'); const Module = await SetupEmscripten.getModule(); + console.log('got module'); if (isWorkerd) { + console.log('im workerd using module'); Module.API.config.indexURL = indexURL; Module.API.config.resolveLockFilePromise!(lockfile); } - setUnsafeEval(UnsafeEval); - setGetRandomValues(getRandomValues); + console.log('im setting stuff module'); + Module.setUnsafeEval(UnsafeEval); + Module.setGetRandomValues(getRandomValues); + console.log('im jaeger'); await enterJaegerSpan('prepare_wasm_linear_memory', () => prepareWasmLinearMemory(Module) ); diff --git a/src/pyodide/pyodide_extra.capnp b/src/pyodide/pyodide_extra.capnp index bce200534c5..b0d8c30cab5 100644 --- a/src/pyodide/pyodide_extra.capnp +++ b/src/pyodide/pyodide_extra.capnp @@ -1,5 +1,5 @@ @0x96c290dbf479ac0c; -const pythonEntrypoint :Text = embed "generated/python-entrypoint.js"; -const pyodidePackagesTar :Data = embed "generated/pyodide_packages.tar"; -const pyodideLock :Text = embed "generated/pyodide-lock.json"; +const pythonEntrypoint :Text = embed "python-entrypoint.js"; +const pyodidePackagesTar :Data = embed "pyodide_packages.tar"; +const pyodideLock :Text = embed "pyodide-lock.json"; diff --git a/src/pyodide/python-entrypoint-helper.ts b/src/pyodide/python-entrypoint-helper.ts index c336d1ffe39..594e5c3d1ed 100644 --- a/src/pyodide/python-entrypoint-helper.ts +++ b/src/pyodide/python-entrypoint-helper.ts @@ -14,13 +14,14 @@ import { import { IS_TRACING, IS_WORKERD, + LOCKFILE, MAIN_MODULE_NAME, + WORKERD_INDEX_URL, } from 'pyodide-internal:metadata'; import { reportError } from 'pyodide-internal:util'; import { default as Limiter } from 'pyodide-internal:limiter'; import { entropyBeforeRequest } from 'pyodide-internal:topLevelEntropy/lib'; import { loadPackages } from 'pyodide-internal:loadPackage'; -import type { default as UnsafeEvalType } from 'internal:unsafe-eval'; function pyimportMainModule(pyodide: Pyodide): PyModule { if (!MAIN_MODULE_NAME.endsWith('.py')) { diff --git a/src/pyodide/types/emscripten.d.ts b/src/pyodide/types/emscripten.d.ts index e465da6c377..5b2ccba9a6f 100644 --- a/src/pyodide/types/emscripten.d.ts +++ b/src/pyodide/types/emscripten.d.ts @@ -68,4 +68,8 @@ interface Module { addRunDependency(x: string): void; removeRunDependency(x: string): void; noInitialRun: boolean; + setUnsafeEval(mod: typeof import('internal:unsafe-eval').default): void; + setGetRandomValues( + func: typeof import('pyodide-internal:topLevelEntropy/lib').getRandomValues + ): void; } diff --git a/src/workerd/api/BUILD.bazel b/src/workerd/api/BUILD.bazel index e15d29244d7..2acb1aeab2d 100644 --- a/src/workerd/api/BUILD.bazel +++ b/src/workerd/api/BUILD.bazel @@ -16,6 +16,7 @@ filegroup( "hyperdrive.c++", "pyodide.c++", "pyodide/pyodide.c++", + "pyodide/setup-emscripten.c++", "rtti.c++", "url.c++", "util.c++", @@ -50,6 +51,7 @@ wd_cc_library( hdrs = [ "modules.h", "rtti.h", + "//src/pyodide:generated/emscripten_setup.capnp.h", "//src/pyodide:generated/pyodide_extra.capnp.h", "//src/workerd/server:workerd.capnp.h", ], @@ -58,6 +60,7 @@ wd_cc_library( ":html-rewriter", ":hyperdrive", "//src/pyodide", + "//src/pyodide:emscripten_setup_capnp", "//src/pyodide:pyodide_extra_capnp", "//src/workerd/api/node", "//src/workerd/io", @@ -93,15 +96,19 @@ wd_cc_library( name = "pyodide", srcs = [ "pyodide/pyodide.c++", + "pyodide/setup-emscripten.c++", ], hdrs = [ "pyodide/pyodide.h", + "pyodide/setup-emscripten.h", + "//src/pyodide:generated/emscripten_setup.capnp.h", "//src/pyodide:generated/pyodide_extra.capnp.h", ], implementation_deps = ["//src/workerd/util:string-buffer"], visibility = ["//visibility:public"], deps = [ "//src/pyodide", + "//src/pyodide:emscripten_setup_capnp", "//src/pyodide:pyodide_extra_capnp", "//src/workerd/io", "//src/workerd/jsg", diff --git a/src/workerd/api/modules.h b/src/workerd/api/modules.h index 4587c403266..8376039bfba 100644 --- a/src/workerd/api/modules.h +++ b/src/workerd/api/modules.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,7 @@ template void registerModules(Registry& registry, auto featureFlags) { node::registerNodeJsCompatModules(registry, featureFlags); if (featureFlags.getPythonWorkers()) { + pyodide::registerSetupEmscriptenModule(registry, featureFlags); pyodide::registerPyodideModules(registry, featureFlags); } registerUnsafeModules(registry, featureFlags); @@ -48,6 +50,7 @@ void registerBuiltinModules(jsg::modules::ModuleRegistry::Builder& builder, auto } if (featureFlags.getPythonWorkers()) { + builder.add(pyodide::getInternalSetupEmscriptenModuleBundle(featureFlags)); builder.add(pyodide::getExternalPyodideModuleBundle(featureFlags)); builder.add(pyodide::getInternalPyodideModuleBundle(featureFlags)); } diff --git a/src/workerd/api/pyodide/setup-emscripten.c++ b/src/workerd/api/pyodide/setup-emscripten.c++ new file mode 100644 index 00000000000..d65b53b40aa --- /dev/null +++ b/src/workerd/api/pyodide/setup-emscripten.c++ @@ -0,0 +1,156 @@ +#include "setup-emscripten.h" + +#include + +namespace workerd::api::pyodide { + +v8::ScriptOrigin ModuleOrigin(v8::Local resource_name) { + v8::ScriptOrigin origin( + resource_name, 0, 0, false, -1, v8::Local(), false, false, true); + return origin; +} +static v8::MaybeLocal CompileSpecifierAsModuleResolveCallback( + v8::Local context, + v8::Local specifier, + v8::Local import_attributes, + v8::Local referrer) { + KJ_DBG("CompileSpecifierAsModuleResolveCallback1"); + KJ_ASSERT(import_attributes->Length() == 0); + v8::Isolate* isolate = context->GetIsolate(); + v8::ScriptOrigin origin = + ModuleOrigin(v8::String::NewFromUtf8(isolate, "emscriptenSetup.js").ToLocalChecked()); + v8::ScriptCompiler::Source source(specifier, origin); + KJ_DBG("CompileSpecifierAsModuleResolveCallback2"); + return v8::ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked(); +} + +void instantiateEmscriptenModule2(jsg::Lock& js, v8::Local& module) { + KJ_DBG("instantiateEmscriptenModule"); + KJ_ASSERT(!module.IsEmpty()); + auto isolate = js.v8Isolate; + auto context = js.v8Context(); + + auto status = module->GetStatus(); + // Nothing to do if the module is already instantiated, evaluated, or errored. + if (status == v8::Module::Status::kInstantiated || status == v8::Module::Status::kEvaluated || + status == v8::Module::Status::kErrored) + return; + + JSG_REQUIRE(status == v8::Module::Status::kUninstantiated, Error, + "Module cannot be synchronously required while it is being instantiated or evaluated. " + "This error typically means that a CommonJS or NodeJS-Compat type module has a circular " + "dependency on itself, and that a synchronous require() is being called while the module " + "is being loaded."); + + jsg::check(module->InstantiateModule(context, CompileSpecifierAsModuleResolveCallback)); + auto prom = jsg::check(module->Evaluate(context)).As(); + js.runMicrotasks(); + + switch (prom->State()) { + case v8::Promise::kPending: + // Let's make sure nobody is depending on pending modules that do not resolve first. + KJ_LOG(ERROR, "Async module was not immediately resolved."); + break; + case v8::Promise::kRejected: + // Since we don't actually support I/O when instantiating a worker, we don't return the + // promise from module->Evaluate, which means we lose any errors that happen during + // instantiation if we don't throw the rejection exception here. + isolate->ThrowException(module->GetException()); + throw jsg::JsExceptionThrown(); + case v8::Promise::kFulfilled: + break; + } + KJ_DBG("instantiateEmscriptenModule2"); +} +jsg::JsValue SetupEmscripten::getModule(jsg::Lock& js) { + KJ_DBG("getModule1"); + jsg::JsValue jsval(pyodide::initializeEmscriptenRuntime(js)); + KJ_DBG("getModule2"); + module_ = jsval.addRef(js); + KJ_DBG("getModule3"); + return KJ_ASSERT_NONNULL(module_).getHandle(js); + // return promise.then(js, [this](jsg::Lock& js, jsg::JsRef emscriptenModule) { + // KJ_DBG("In SetupEmscripten::getModule3"); + // module_ = kj::mv(emscriptenModule); + // return KJ_ASSERT_NONNULL(module_).getHandle(js); + // }); + // funcres.As()->Then(js.v8Context(), [](v8::Local, v8::Local) { + // auto instantiateEmscriptenModule = + // KJ_ASSERT_NONNULL(handler.tryUnwrap(js, result.As())); + // auto& context = IoContext::current(); + // return instantiateEmscriptenModule(js, js.str(EMSCRIPTEN_SETUP->getPythonStdlibZip()), + // js.str(EMSCRIPTEN_SETUP->getPyodideAsmWasm())) + // .then(js, [this](jsg::Lock& js, jsg::JsRef emscriptenModule) { + // KJ_DBG("In SetupEmscripten::getModule3"); + // module_ = kj::mv(emscriptenModule); + // return KJ_ASSERT_NONNULL(module_).getHandle(js); + // }); + // return context.awaitIo(js, + // instantiateEmscriptenModule(js, js.str("a"_kjc), js.str("a"_kjc)), + // [this](jsg::Lock& js, jsg::JsRef result) { + // module_ = kj::mv(result); + // return KJ_ASSERT_NONNULL(module_).getHandle(js); + // }); +} + +v8::Local initializeEmscriptenRuntime(jsg::Lock& js) { + js.setAllowEval(true); + KJ_DEFER(js.setAllowEval(false)); + KJ_DBG("In SetupEmscripten::getModule"); + + v8::Local contentStr = + jsg::v8Str(js.v8Isolate, EMSCRIPTEN_SETUP->getCode().asArray()); + v8::ScriptOrigin origin = ModuleOrigin(jsg::v8StrIntern(js.v8Isolate, "emscriptenSetup.js")); + v8::ScriptCompiler::Source source(contentStr, origin); + + v8::Local module; + if (!v8::ScriptCompiler::CompileModule(js.v8Isolate, &source).ToLocal(&module)) { + KJ_FAIL_ASSERT("Emscripten Setup code didn't parse"); + } + instantiateEmscriptenModule2(js, module); + + auto handle = jsg::check(module->Evaluate(js.v8Context())); + KJ_ASSERT(handle->IsPromise()); + auto prom = handle.As(); + if (prom->State() == v8::Promise::PromiseState::kPending) { + js.runMicrotasks(); + } + KJ_ASSERT(prom->State() != v8::Promise::PromiseState::kPending); + KJ_ASSERT(module->GetStatus() != v8::Module::kErrored); + auto result = + js.v8Get(module->GetModuleNamespace().As(), "instantiateEmscriptenModule"_kj); + + auto src = EMSCRIPTEN_SETUP->getPyodideAsmWasm(); + auto wasmModule = jsg::check(v8::WasmModuleObject::Compile( + js.v8Isolate, v8::MemorySpan(src.begin(), src.size()))); + auto arg2Buffer = + v8::ArrayBuffer::New(js.v8Isolate, EMSCRIPTEN_SETUP->getPythonStdlibZip().size(), + v8::BackingStoreInitializationMode::kUninitialized); + memcpy(arg2Buffer->Data(), EMSCRIPTEN_SETUP->getPythonStdlibZip().begin(), + EMSCRIPTEN_SETUP->getPythonStdlibZip().size()); + // auto arg3Buffer = v8::ArrayBuffer::New(js.v8Isolate, EMSCRIPTEN_SETUP->getPyodideAsmWasm().size(), + // v8::BackingStoreInitializationMode::kUninitialized); + // memcpy(arg3Buffer->Data(), EMSCRIPTEN_SETUP->getPyodideAsmWasm().begin(), + // EMSCRIPTEN_SETUP->getPyodideAsmWasm().size()); + + v8::LocalVector argv(js.v8Isolate, 3); + argv[0] = v8::Boolean::New(js.v8Isolate, true); + argv[1] = kj::mv(arg2Buffer); + argv[2] = kj::mv(wasmModule); + KJ_DBG("1111"); + auto funcres = jsg::check( + result.As()->Call(js.v8Context(), js.v8Null(), argv.size(), argv.data())); + KJ_DBG("2222"); + auto promise = funcres.As(); + KJ_DBG("In SetupEmscripten::getModule2"); + if (promise->State() == v8::Promise::PromiseState::kPending) { + KJ_DBG("3333"); + js.runMicrotasks(); + } + KJ_DBG("3334"); + KJ_ASSERT(promise->State() == v8::Promise::PromiseState::kFulfilled); + auto promresult = promise->Result(); + KJ_ASSERT(promresult->IsObject()); + return promresult; +} +} // namespace workerd::api::pyodide diff --git a/src/workerd/api/pyodide/setup-emscripten.h b/src/workerd/api/pyodide/setup-emscripten.h new file mode 100644 index 00000000000..169aae839cf --- /dev/null +++ b/src/workerd/api/pyodide/setup-emscripten.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include + +namespace workerd::api::pyodide { + +class EmscriptenModule: public jsg::Object { +public: + explicit EmscriptenModule(jsg::Lock& js) {}; + JSG_STRUCT(EmscriptenModule); + +private: +}; + +using instantiateEmscriptenModuleFunction = jsg::Function>( + jsg::JsBoolean, jsg::JsString, jsg::JsString)>; + +class SetupEmscripten: public jsg::Object { +public: + SetupEmscripten() { + KJ_DBG("Default empty constructor", kj::getStackTrace()); + }; + SetupEmscripten(jsg::Lock& js, const jsg::Url&) { + KJ_DBG("Jslock constructor", kj::getStackTrace()); + } + + jsg::JsValue getModule(jsg::Lock& js); + + JSG_RESOURCE_TYPE(SetupEmscripten) { + JSG_METHOD(getModule); + } + +private: + kj::Maybe> module_; +}; + +#define EW_SETUP_EMSCRIPTEN_ISOLATE_TYPES api::pyodide::SetupEmscripten + +template +void registerSetupEmscriptenModule(Registry& registry, auto featureFlags) { + registry.template addBuiltinModule( + "internal:setup-emscripten", workerd::jsg::ModuleRegistry::Type::INTERNAL); +} + +template +kj::Own getInternalSetupEmscriptenModuleBundle(auto featureFlags) { + jsg::modules::ModuleBundle::BuiltinBuilder builder( + jsg::modules::ModuleBundle::BuiltinBuilder::Type::BUILTIN_ONLY); + static const auto kSpecifier = "internal:setup-emscripten"_url; + builder.addObject(kSpecifier); + return builder.finish(); +} + +v8::Local initializeEmscriptenRuntime(jsg::Lock&); + +} // namespace workerd::api::pyodide diff --git a/src/workerd/jsg/modules.c++ b/src/workerd/jsg/modules.c++ index d3c70eb7967..aa3df9b2648 100644 --- a/src/workerd/jsg/modules.c++ +++ b/src/workerd/jsg/modules.c++ @@ -352,6 +352,10 @@ NonModuleScript NonModuleScript::compile(kj::StringPtr code, jsg::Lock& js, kj:: } void instantiateModule(jsg::Lock& js, v8::Local& module) { + static int counter = 0; + if (counter++ == 1) { + // KJ_FAIL_ASSERT("InstantiateModule() is not implemented yet."); + } KJ_ASSERT(!module.IsEmpty()); auto isolate = js.v8Isolate; auto context = js.v8Context(); @@ -368,10 +372,14 @@ void instantiateModule(jsg::Lock& js, v8::Local& module) { "dependency on itself, and that a synchronous require() is being called while the module " "is being loaded."); + KJ_DBG("module->InstantiateModule"); jsg::check(module->InstantiateModule(context, &resolveCallback)); + KJ_DBG("module->Evaluate"); auto prom = jsg::check(module->Evaluate(context)).As(); + KJ_DBG("js.runMicrotasks"); js.runMicrotasks(); + KJ_DBG("switch"); switch (prom->State()) { case v8::Promise::kPending: // Let's make sure nobody is depending on pending modules that do not resolve first. diff --git a/src/workerd/jsg/setup.c++ b/src/workerd/jsg/setup.c++ index 264903fb76a..2d5ef7b882f 100644 --- a/src/workerd/jsg/setup.c++ +++ b/src/workerd/jsg/setup.c++ @@ -357,6 +357,7 @@ IsolateBase::IsolateBase(const V8System& system, [](v8::Isolate* isolate, v8::Local context, v8::Local resolver, v8::Local result, v8::WasmAsyncSuccess success) { + KJ_DBG("SetWasmAsyncResolvePromiseCallback"); switch (success) { case v8::WasmAsyncSuccess::kSuccess: resolver->Resolve(context, result).FromJust(); diff --git a/src/workerd/server/workerd-api.c++ b/src/workerd/server/workerd-api.c++ index 1140ae2febf..b13973733d3 100644 --- a/src/workerd/server/workerd-api.c++ +++ b/src/workerd/server/workerd-api.c++ @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +112,7 @@ JSG_DECLARE_ISOLATE_TYPE(JsgWorkerdIsolate, #ifdef WORKERD_EXPERIMENTAL_ENABLE_WEBGPU EW_WEBGPU_ISOLATE_TYPES, #endif + EW_SETUP_EMSCRIPTEN_ISOLATE_TYPES, jsg::TypeWrapperExtension, jsg::InjectConfiguration, @@ -167,7 +169,20 @@ struct WorkerdApi::Impl final { jsgIsolate( v8System, Configuration(*this), kj::mv(observer), limitEnforcer.getCreateParams()), memoryCacheProvider(memoryCacheProvider), - pythonConfig(pythonConfig) {} + pythonConfig(pythonConfig) { + // if (featuresParam.getPythonWorkers()) { + // jsgIsolate.runInLockScope([&](JsgWorkerdIsolate::Lock& lock) { + // js.withinHandleScope([&]() -> auto { + // v8::Local ctx = v8::Context::New(js.v8Isolate); + // KJ_ASSERT(!ctx.IsEmpty(), "unable to enter invalid v8::Context"); + // v8::Context::Scope scope(ctx); + // // Init emscripten syncronously, the python script will import setup-emscripten and + // // call setEmscriptenModele + // api::pyodide::initializeEmscriptenRuntime(lock); + // }); + // }); + // } + } static v8::Local compileTextGlobal( JsgWorkerdIsolate::Lock& lock, capnp::Text::Reader reader) {