diff options
author | 2023-01-02 02:37:45 +0200 | |
---|---|---|
committer | 2023-01-01 16:37:45 -0800 | |
commit | 8a29c643025c73312da001c5fa4caf0ccf0528fa (patch) | |
tree | 487fb73334b0eda6484b331886f80a4664dfccb0 | |
parent | 2345e268bc8f38ffdeba1580780e96683600874b (diff) | |
download | bun-8a29c643025c73312da001c5fa4caf0ccf0528fa.tar.gz bun-8a29c643025c73312da001c5fa4caf0ccf0528fa.tar.zst bun-8a29c643025c73312da001c5fa4caf0ccf0528fa.zip |
clean up `Promise` handling (#1697)
-rw-r--r-- | src/bun.js/api/bun.zig | 2 | ||||
-rw-r--r-- | src/bun.js/api/bun/socket.zig | 4 | ||||
-rw-r--r-- | src/bun.js/api/bun/subprocess.zig | 6 | ||||
-rw-r--r-- | src/bun.js/api/html_rewriter.zig | 15 | ||||
-rw-r--r-- | src/bun.js/api/server.zig | 29 | ||||
-rw-r--r-- | src/bun.js/base.zig | 14 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 64 | ||||
-rw-r--r-- | src/bun.js/event_loop.zig | 14 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 18 | ||||
-rw-r--r-- | src/bun.js/module_loader.zig | 2 | ||||
-rw-r--r-- | src/bun.js/test/jest.zig | 37 | ||||
-rw-r--r-- | src/bun.js/webcore/response.zig | 62 | ||||
-rw-r--r-- | src/js_ast.zig | 20 | ||||
-rw-r--r-- | src/napi/napi.zig | 2 |
14 files changed, 127 insertions, 162 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 31d536000..6b19f138d 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -2855,7 +2855,7 @@ pub const Timer = struct { return; } - if (result.asPromise()) |promise| { + if (result.asAnyPromise()) |promise| { switch (promise.status(globalThis.vm())) { .Rejected => { this.deinit(); diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index cbee356f2..1b0df92f5 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -83,13 +83,13 @@ const Handlers = struct { pub fn resolvePromise(this: *Handlers, value: JSValue) void { var promise = this.promise.get() orelse return; this.promise.deinit(); - promise.asPromise().?.resolve(this.globalObject, value); + promise.asAnyPromise().?.resolve(this.globalObject, value); } pub fn rejectPromise(this: *Handlers, value: JSValue) bool { var promise = this.promise.get() orelse return false; this.promise.deinit(); - promise.asPromise().?.reject(this.globalObject, value); + promise.asAnyPromise().?.reject(this.globalObject, value); return true; } diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 6352c936d..3f667491b 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -1516,12 +1516,12 @@ pub const Subprocess = struct { if (this.hasExited()) { if (this.exit_promise.trySwap()) |promise| { if (this.exit_code) |code| { - promise.asPromise().?.resolve(globalThis, JSValue.jsNumber(code)); + promise.asAnyPromise().?.resolve(globalThis, JSValue.jsNumber(code)); } else if (this.signal_code != null) { - promise.asPromise().?.resolve(globalThis, this.getSignalCode(globalThis)); + promise.asAnyPromise().?.resolve(globalThis, this.getSignalCode(globalThis)); } else if (this.waitpid_err) |err| { this.waitpid_err = null; - promise.asPromise().?.reject(globalThis, err.toJSC(globalThis)); + promise.asAnyPromise().?.reject(globalThis, err.toJSC(globalThis)); } else { // crash in debug mode if (comptime Environment.allow_assert) diff --git a/src/bun.js/api/html_rewriter.zig b/src/bun.js/api/html_rewriter.zig index 05b110b90..f5abdc734 100644 --- a/src/bun.js/api/html_rewriter.zig +++ b/src/bun.js/api/html_rewriter.zig @@ -842,14 +842,7 @@ fn HandlerCallback( return true; } - if (result.asPromise()) |promise| { - this.global.bunVM().waitForPromise(promise); - const fail = promise.status(this.global.vm()) == .Rejected; - if (fail) { - this.global.bunVM().runErrorHandler(promise.result(this.global.vm()), null); - } - return fail; - } else if (result.asInternalPromise()) |promise| { + if (result.asAnyPromise()) |promise| { this.global.bunVM().waitForPromise(promise); const fail = promise.status(this.global.vm()) == .Rejected; if (fail) { @@ -1462,13 +1455,13 @@ pub const AttributeIterator = struct { \\ } \\ \\ #iterator; - \\ + \\ \\ [Symbol.iterator]() { \\ return this; \\ } - \\ + \\ \\ next() { - \\ if (this.#iterator === null) + \\ if (this.#iterator === null) \\ return {done: true}; \\ var value = this.#iterator.next(); \\ if (!value) { diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 384db3a60..e06e1337e 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -999,7 +999,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp if (this.promise) |promise| { this.pending_promises_for_abort += 1; this.promise = null; - promise.asPromise().?.reject(this.server.globalThis, JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis)); + promise.asAnyPromise().?.reject(this.server.globalThis, JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis)); } if (this.pending_promises_for_abort > 0) { @@ -1052,9 +1052,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp if (this.promise) |promise| { this.promise = null; - if (promise.asInternalPromise()) |prom| { - prom.rejectAsHandled(this.server.globalThis, (JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis))); - } else if (promise.asPromise()) |prom| { + if (promise.asAnyPromise()) |prom| { prom.rejectAsHandled(this.server.globalThis, (JSC.toTypeError(.ABORT_ERR, "Request aborted", .{}, this.server.globalThis))); } JSC.C.JSValueUnprotect(this.server.globalThis, promise.asObjectRef()); @@ -1520,7 +1518,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp if (!assignment_result.isEmptyOrUndefinedOrNull()) { assignment_result.ensureStillAlive(); // it returns a Promise when it goes through ReadableStreamDefaultReader - if (assignment_result.asPromise()) |promise| { + if (assignment_result.asAnyPromise()) |promise| { streamLog("returned a promise", .{}); switch (promise.status(this.server.globalThis.vm())) { .Pending => { @@ -1661,7 +1659,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp var wait_for_promise = false; var vm = this.vm; - if (response_value.asPromise()) |promise| { + if (response_value.asAnyPromise()) |promise| { // If we immediately have the value available, we can skip the extra event loop tick switch (promise.status(vm.global.vm())) { .Pending => {}, @@ -1713,21 +1711,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp }, } wait_for_promise = true; - // I don't think this case should happen - // But I'm uncertain - } else if (response_value.asInternalPromise()) |promise| { - switch (promise.status(vm.global.vm())) { - .Pending => {}, - .Fulfilled => { - ctx.handleResolve(promise.result(vm.global.vm())); - return; - }, - .Rejected => { - ctx.handleReject(promise.result(vm.global.vm())); - return; - }, - } - wait_for_promise = true; } if (wait_for_promise) { @@ -2900,7 +2883,7 @@ pub const ServerWebSocket = struct { return; } - if (result.asPromise()) |promise| { + if (result.asAnyPromise()) |promise| { switch (promise.status(globalObject.vm())) { .Rejected => { _ = promise.result(globalObject.vm()); @@ -4216,7 +4199,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { return JSC.JSPromise.rejectedPromiseValue(ctx, ZigString.init("fetch() returned an empty value").toErrorInstance(ctx)).asObjectRef(); } - if (response_value.asPromise() != null) { + if (response_value.asAnyPromise() != null) { return response_value.asObjectRef(); } diff --git a/src/bun.js/base.zig b/src/bun.js/base.zig index de02c1cbf..671a4c197 100644 --- a/src/bun.js/base.zig +++ b/src/bun.js/base.zig @@ -2538,7 +2538,7 @@ pub fn DOMCall( \\ static const JSC::DOMJIT::Signature {[signatureName]s}( \\ {[fastPathName]s}Wrapper, \\ thisObject->classInfo(), - \\ + \\ ; try writer.print(fmt, .{ @@ -2823,16 +2823,10 @@ pub fn wrapWithHasContainer( } if (comptime maybe_async) { - if (result.asPromise() != null or result.asInternalPromise() != null) { + if (result.asAnyPromise()) |promise| { var vm = ctx.ptr().bunVM(); - - if (result.asPromise()) |promise| { - vm.waitForPromise(promise); - result = promise.result(ctx.vm()); - } else if (result.asInternalPromise()) |promise| { - vm.waitForPromise(promise); - result = promise.result(ctx.vm()); - } + vm.waitForPromise(promise); + result = promise.result(ctx.vm()); } } diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 8d940a0aa..942d4b4f1 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -1802,6 +1802,54 @@ pub const JSInternalPromise = extern struct { }; }; +pub const AnyPromise = union(enum) { + Normal: *JSPromise, + Internal: *JSInternalPromise, + + pub fn status(this: AnyPromise, vm: *VM) JSPromise.Status { + return switch (this) { + inline else => |promise| promise.status(vm), + }; + } + pub fn result(this: AnyPromise, vm: *VM) JSValue { + return switch (this) { + inline else => |promise| promise.result(vm), + }; + } + pub fn isHandled(this: AnyPromise, vm: *VM) bool { + return switch (this) { + inline else => |promise| promise.isHandled(vm), + }; + } + + pub fn rejectWithCaughtException(this: AnyPromise, globalObject: *JSGlobalObject, scope: ThrowScope) void { + switch (this) { + inline else => |promise| promise.rejectWithCaughtException(globalObject, scope), + } + } + + pub fn resolve(this: AnyPromise, globalThis: *JSGlobalObject, value: JSValue) void { + switch (this) { + inline else => |promise| promise.resolve(globalThis, value), + } + } + pub fn reject(this: AnyPromise, globalThis: *JSGlobalObject, value: JSValue) void { + switch (this) { + inline else => |promise| promise.reject(globalThis, value), + } + } + pub fn rejectAsHandled(this: AnyPromise, globalThis: *JSGlobalObject, value: JSValue) void { + switch (this) { + inline else => |promise| promise.rejectAsHandled(globalThis, value), + } + } + pub fn rejectAsHandledException(this: AnyPromise, globalThis: *JSGlobalObject, value: *Exception) void { + switch (this) { + inline else => |promise| promise.rejectAsHandledException(globalThis, value), + } + } +}; + // SourceProvider.h pub const SourceType = enum(u8) { Program = 0, @@ -2762,6 +2810,22 @@ pub const JSValue = enum(JSValueReprInt) { }); } + pub fn asAnyPromise( + value: JSValue, + ) ?AnyPromise { + if (value.asInternalPromise()) |promise| { + return AnyPromise{ + .Internal = promise, + }; + } + if (value.asPromise()) |promise| { + return AnyPromise{ + .Normal = promise, + }; + } + return null; + } + pub fn jsNumber(number: anytype) JSValue { return jsNumberWithType(@TypeOf(number), number); } diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 56e68cce0..c5927298a 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -529,19 +529,7 @@ pub const EventLoop = struct { } } - // TODO: fix this technical debt - pub fn waitForPromise(this: *EventLoop, promise: anytype) void { - return waitForPromiseWithType(this, std.meta.Child(@TypeOf(promise)), promise); - } - - pub fn waitForPromiseWithType(this: *EventLoop, comptime Promise: type, promise: *Promise) void { - comptime { - switch (Promise) { - JSC.JSPromise, JSC.JSInternalPromise => {}, - else => @compileError("Promise must be a JSPromise or JSInternalPromise, received: " ++ @typeName(Promise)), - } - } - + pub fn waitForPromise(this: *EventLoop, promise: JSC.AnyPromise) void { switch (promise.status(this.global.vm())) { JSC.JSPromise.Status.Pending => { while (promise.status(this.global.vm()) == .Pending) { diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index e0b8a5376..713ab7264 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -571,7 +571,7 @@ pub const VirtualMachine = struct { this.eventLoop().tick(); } - pub fn waitForPromise(this: *VirtualMachine, promise: anytype) void { + pub fn waitForPromise(this: *VirtualMachine, promise: JSC.AnyPromise) void { this.eventLoop().waitForPromise(promise); } @@ -1308,7 +1308,9 @@ pub const VirtualMachine = struct { if (this.node_modules != null and !this.has_loaded_node_modules) { this.has_loaded_node_modules = true; promise = JSModuleLoader.loadAndEvaluateModule(this.global, ZigString.static(bun_file_import_path)); - this.waitForPromise(promise); + this.waitForPromise(JSC.AnyPromise{ + .Internal = promise, + }); if (promise.status(this.global.vm()) == .Rejected) return promise; } @@ -1343,7 +1345,9 @@ pub const VirtualMachine = struct { } } else { this.eventLoop().performGC(); - this.waitForPromise(promise); + this.waitForPromise(JSC.AnyPromise{ + .Internal = promise, + }); } this.eventLoop().autoTick(); @@ -1390,7 +1394,9 @@ pub const VirtualMachine = struct { var promise: *JSInternalPromise = undefined; promise = JSModuleLoader.loadAndEvaluateModule(this.global, &ZigString.init(entry_path)); - this.waitForPromise(promise); + this.waitForPromise(JSC.AnyPromise{ + .Internal = promise, + }); return promise; } @@ -2032,7 +2038,9 @@ pub const EventListenerMixin = struct { vm.tick(); var promise = JSInternalPromise.resolvedPromise(vm.global, result); - vm.event_loop.waitForPromise(promise); + vm.event_loop.waitForPromise(JSC.AnyPromise{ + .Internal = promise, + }); if (fetch_event.rejected) return; diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index 54dc3d88a..cf433414f 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -1311,7 +1311,7 @@ pub const ModuleLoader = struct { } if (!promise.isEmptyOrUndefinedOrNull()) { - if (promise.asInternalPromise()) |promise_value| { + if (promise.asAnyPromise()) |promise_value| { jsc_vm.waitForPromise(promise_value); if (promise_value.status(jsc_vm.global.vm()) == .Rejected) { diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index b8b0e8ded..6870bb93e 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -1323,14 +1323,19 @@ pub const TestScope = struct { return .{ .fail = active_test_expectation_counter.actual }; } - if (initial_value.jsType() == .JSPromise) { + if (initial_value.asAnyPromise()) |promise| { if (this.promise != null) { return .{ .pending = {} }; } - - var promise: *JSC.JSPromise = initial_value.asPromise().?; this.task = task; + // TODO: not easy to coerce JSInternalPromise as JSValue, + // so simply wait for completion for now. + switch (promise) { + .Internal => vm.waitForPromise(promise), + else => {}, + } + switch (promise.status(vm.global.vm())) { .Rejected => { vm.runErrorHandler(promise.result(vm.global.vm()), null); @@ -1338,8 +1343,13 @@ pub const TestScope = struct { }, .Pending => { task.promise_state = .pending; - _ = promise.asValue(vm.global).then(vm.global, task, onResolve, onReject); - return .{ .pending = {} }; + switch (promise) { + .Normal => |p| { + _ = p.asValue(vm.global).then(vm.global, task, onResolve, onReject); + return .{ .pending = {} }; + }, + else => unreachable, + } }, else => { @@ -1517,6 +1527,7 @@ pub const DescribeScope = struct { const pending_test = Jest.runner.?.pending_test; // forbid `expect()` within hooks Jest.runner.?.pending_test = null; + const vm = VirtualMachine.get(); var result: JSC.JSValue = if (cb.getLengthOfArray(ctx) > 0) brk: { this.done = false; const done_func = JSC.NewFunctionWithData( @@ -1528,7 +1539,6 @@ pub const DescribeScope = struct { this, ); var result = cb.call(ctx, &.{done_func}); - var vm = VirtualMachine.get(); while (!this.done) { vm.eventLoop().autoTick(); if (this.done) break; @@ -1536,10 +1546,10 @@ pub const DescribeScope = struct { } break :brk result; } else cb.call(ctx, &.{}); - if (result.asPromise()) |promise| { + if (result.asAnyPromise()) |promise| { if (promise.status(ctx.vm()) == .Pending) { result.protect(); - VirtualMachine.get().waitForPromise(promise); + vm.waitForPromise(promise); result.unprotect(); } @@ -1623,16 +1633,7 @@ pub const DescribeScope = struct { JSC.markBinding(@src()); var result = js.JSObjectCallAsFunctionReturnValue(ctx, callback, thisObject, 0, null); - if (result.asPromise()) |prom| { - ctx.bunVM().waitForPromise(prom); - switch (prom.status(ctx.ptr().vm())) { - JSPromise.Status.Fulfilled => {}, - else => { - exception.* = prom.result(ctx.ptr().vm()).asObjectRef(); - return null; - }, - } - } else if (result.asPromise()) |prom| { + if (result.asAnyPromise()) |prom| { ctx.bunVM().waitForPromise(prom); switch (prom.status(ctx.ptr().vm())) { JSPromise.Status.Fulfilled => {}, diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index 1ed29f196..20a04137f 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -613,7 +613,7 @@ pub const Fetch = struct { return; } - var promise = promise_value.asPromise().?; + const promise = promise_value.asAnyPromise().?; const success = this.result.isSuccess(); const result = switch (success) { @@ -1171,22 +1171,7 @@ pub const Blob = struct { var blob = value.use(); // TODO: this should be one promise not two! const new_promise = writeFileWithSourceDestination(globalThis, &blob, &file_blob); - if (JSC.JSValue.fromRef(new_promise.?).asPromise()) |_promise| { - switch (_promise.status(globalThis.vm())) { - .Pending => { - promise.resolve( - globalThis, - JSC.JSValue.fromRef(new_promise.?), - ); - }, - .Rejected => { - promise.reject(globalThis, _promise.result(globalThis.vm())); - }, - else => { - promise.resolve(globalThis, _promise.result(globalThis.vm())); - }, - } - } else if (JSC.JSValue.fromRef(new_promise.?).asInternalPromise()) |_promise| { + if (JSC.JSValue.fromRef(new_promise.?).asAnyPromise()) |_promise| { switch (_promise.status(globalThis.vm())) { .Pending => { promise.resolve( @@ -4896,7 +4881,7 @@ pub const Body = struct { } if (locked.promise) |promise_| { - var promise = promise_.asPromise().?; + const promise = promise_.asAnyPromise().?; locked.promise = null; switch (locked.action) { @@ -4929,18 +4914,11 @@ pub const Body = struct { var blob = new.useAsAnyBlob(); promise.resolve(global, blob.toArrayBuffer(global, .transfer)); }, - .getBlob => { - var ptr = bun.default_allocator.create(Blob) catch unreachable; - ptr.* = new.use(); - - ptr.allocator = bun.default_allocator; - promise.resolve(global, ptr.toJS(global)); - }, else => { var ptr = bun.default_allocator.create(Blob) catch unreachable; ptr.* = new.use(); ptr.allocator = bun.default_allocator; - promise_.asInternalPromise().?.resolve(global, ptr.toJS(global)); + promise.resolve(global, ptr.toJS(global)); }, } JSC.C.JSValueUnprotect(global, promise_.asObjectRef()); @@ -5031,9 +5009,7 @@ pub const Body = struct { var locked = this.Locked; locked.deinit = true; if (locked.promise) |promise| { - if (promise.asInternalPromise()) |internal| { - internal.reject(global, error_instance); - } else if (promise.asPromise()) |internal| { + if (promise.asAnyPromise()) |internal| { internal.reject(global, error_instance); } JSC.C.JSValueUnprotect(global, promise.asObjectRef()); @@ -5835,33 +5811,7 @@ pub const FetchEvent = struct { } } - if (this.pending_promise.asPromise()) |promise| { - switch (promise.status(ctx.vm())) { - JSC.JSPromise.Status.Pending => { - while (promise.status(ctx.vm()) == .Pending) { - ctx.bunVM().tick(); - } - }, - else => {}, - } - - switch (promise.status(ctx.ptr().vm())) { - .Fulfilled => {}, - else => { - this.rejected = true; - this.pending_promise = JSValue.zero; - this.onPromiseRejectionHandler.?( - this.onPromiseRejectionCtx, - error.PromiseRejection, - this, - promise.result(globalThis.vm()), - ); - return js.JSValueMakeUndefined(ctx); - }, - } - - arg = promise.result(ctx.ptr().vm()).asRef(); - } else if (this.pending_promise.asInternalPromise()) |promise| { + if (this.pending_promise.asAnyPromise()) |promise| { globalThis.bunVM().waitForPromise(promise); switch (promise.status(ctx.ptr().vm())) { diff --git a/src/js_ast.zig b/src/js_ast.zig index 7e5d346e2..691ff791a 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -8119,24 +8119,8 @@ pub const Macro = struct { var promise_result = JSC.JSValue.zero; var rejected = false; - if (value.asPromise()) |promise| { - while (true) { - if (promise.status(this.global.vm()) != .Pending) break; - this.macro.vm.tick(); - if (promise.status(this.global.vm()) != .Pending) break; - this.macro.vm.eventLoop().autoTick(); - } - - promise_result = promise.result(this.global.vm()); - rejected = promise.status(this.global.vm()) == .Rejected; - } else if (value.asInternalPromise()) |promise| { - while (true) { - if (promise.status(this.global.vm()) != .Pending) break; - this.macro.vm.tick(); - if (promise.status(this.global.vm()) != .Pending) break; - this.macro.vm.eventLoop().autoTick(); - } - + if (value.asAnyPromise()) |promise| { + this.macro.vm.waitForPromise(promise); promise_result = promise.result(this.global.vm()); rejected = promise.status(this.global.vm()) == .Rejected; } else { diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 5e4afa7b0..cfc379aab 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -833,7 +833,7 @@ pub export fn napi_is_promise(_: napi_env, value: napi_value, is_promise: *bool) return .ok; } - is_promise.* = value.asPromise() != null or value.asInternalPromise() != null; + is_promise.* = value.asAnyPromise() != null; return .ok; } pub export fn napi_run_script(env: napi_env, script: napi_value, result: *napi_value) napi_status { |