Skip to content

Commit

Permalink
Enable JSPI
Browse files Browse the repository at this point in the history
This enables JSPI in Python workers. It will not be usable until we
also update to the newer Pyodide runtime.
  • Loading branch information
hoodmane committed Dec 19, 2024
1 parent 7d0e7cd commit 095b7c4
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/workerd/api/pyodide/pyodide.c++
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ void DiskCache::put(jsg::Lock& js, kj::String key, kj::Array<kj::byte> data) {
}

jsg::JsValue SetupEmscripten::getModule(jsg::Lock& js) {
js.installJspi();
js.v8Context()->SetSecurityToken(emscriptenRuntime.contextToken.getHandle(js));
return emscriptenRuntime.emscriptenRuntime.getHandle(js);
}
Expand Down
1 change: 1 addition & 0 deletions src/workerd/api/pyodide/setup-emscripten.c++
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ EmscriptenRuntime EmscriptenRuntime::initialize(
kj::Maybe<capnp::Data::Reader> emsciptenSetupJsReader;
kj::Maybe<capnp::Data::Reader> pythonStdlibZipReader;
kj::Maybe<capnp::Data::Reader> pyodideAsmWasmReader;
js.installJspi();
for (auto module: bundle.getModules()) {
if (module.getName().endsWith("emscriptenSetup.js")) {
emsciptenSetupJsReader = module.getData();
Expand Down
6 changes: 6 additions & 0 deletions src/workerd/jsg/jsg.c++
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ void Lock::setAllowEval(bool allow) {
IsolateBase::from(v8Isolate).setAllowEval({}, allow);
}

void Lock::installJspi() {
IsolateBase::from(v8Isolate).setJspiEnabled({}, true);
v8Isolate->InstallConditionalFeatures(v8Context());
IsolateBase::from(v8Isolate).setJspiEnabled({}, false);
}

void Lock::setCaptureThrowsAsRejections(bool capture) {
IsolateBase::from(v8Isolate).setCaptureThrowsAsRejections({}, capture);
}
Expand Down
1 change: 1 addition & 0 deletions src/workerd/jsg/jsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -2527,6 +2527,7 @@ class Lock {

// Use to enable/disable dynamic code evaluation (via eval(), new Function(), or WebAssembly).
void setAllowEval(bool allow);
void installJspi();

void setCaptureThrowsAsRejections(bool capture);
void setCommonJsExportDefault(bool exportDefault);
Expand Down
8 changes: 8 additions & 0 deletions src/workerd/jsg/setup.c++
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ IsolateBase::IsolateBase(const V8System& system,

ptr->SetModifyCodeGenerationFromStringsCallback(&modifyCodeGenCallback);
ptr->SetAllowWasmCodeGenerationCallback(&allowWasmCallback);
ptr->SetWasmJSPIEnabledCallback(&jspiEnabledCallback);

// We don't support SharedArrayBuffer so Atomics.wait() doesn't make sense, and might allow DoS
// attacks.
Expand Down Expand Up @@ -461,6 +462,13 @@ bool IsolateBase::allowWasmCallback(v8::Local<v8::Context> context, v8::Local<v8
return self->evalAllowed;
}

bool IsolateBase::jspiEnabledCallback(v8::Local<v8::Context> context) {
IsolateBase* self =
static_cast<IsolateBase*>(context->GetIsolate()->GetData(SET_DATA_ISOLATE_BASE));
KJ_DBG("Called jspiEnabledCallback", self->jspiEnabled);
return true;
}

void IsolateBase::jitCodeEvent(const v8::JitCodeEvent* event) noexcept {
// We register this callback with V8 in order to build a mapping of code addresses to source
// code locations, which we use when reporting stack traces during crashes.
Expand Down
5 changes: 5 additions & 0 deletions src/workerd/jsg/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ class IsolateBase {
inline void setAllowEval(kj::Badge<Lock>, bool allow) {
evalAllowed = allow;
}
inline void setJspiEnabled(kj::Badge<Lock>, bool enabled) {
jspiEnabled = enabled;
}
inline void setCaptureThrowsAsRejections(kj::Badge<Lock>, bool capture) {
captureThrowsAsRejections = capture;
}
Expand Down Expand Up @@ -236,6 +239,7 @@ class IsolateBase {
v8::Isolate* ptr;
kj::Maybe<kj::String> uuid;
bool evalAllowed = false;
bool jspiEnabled = false;

// The Web Platform API specifications require that any API that returns a JavaScript Promise
// should never throw errors synchronously. Rather, they are supposed to capture any synchronous
Expand Down Expand Up @@ -320,6 +324,7 @@ class IsolateBase {
static v8::ModifyCodeGenerationFromStringsResult modifyCodeGenCallback(
v8::Local<v8::Context> context, v8::Local<v8::Value> source, bool isCodeLike);
static bool allowWasmCallback(v8::Local<v8::Context> context, v8::Local<v8::String> source);
static bool jspiEnabledCallback(v8::Local<v8::Context> context);

static void jitCodeEvent(const v8::JitCodeEvent* event) noexcept;

Expand Down
1 change: 1 addition & 0 deletions src/workerd/server/tests/python/hello/worker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
def test():
from js.WebAssembly import Suspending
# This just tests that nothing raises when we run this. It isn't great though
# because we don't test whether we printed anything.
# TODO: update this to test that something happened
Expand Down

0 comments on commit 095b7c4

Please sign in to comment.