summaryrefslogtreecommitdiff
path: root/ext/ffi/00_ffi.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ffi/00_ffi.js')
-rw-r--r--ext/ffi/00_ffi.js115
1 files changed, 85 insertions, 30 deletions
diff --git a/ext/ffi/00_ffi.js b/ext/ffi/00_ffi.js
index b0bdbe8cf..abe806cc0 100644
--- a/ext/ffi/00_ffi.js
+++ b/ext/ffi/00_ffi.js
@@ -142,6 +142,84 @@
}
}
+ function prepareArgs(types, args) {
+ const parameters = [];
+ const buffers = [];
+
+ for (let i = 0; i < types.length; i++) {
+ const type = types[i];
+ const arg = args[i];
+
+ if (type === "pointer") {
+ if (
+ arg?.buffer instanceof ArrayBuffer &&
+ arg.byteLength !== undefined
+ ) {
+ parameters.push(buffers.length);
+ buffers.push(arg);
+ } else if (arg instanceof UnsafePointer) {
+ parameters.push(packU64(arg.value));
+ buffers.push(undefined);
+ } else if (arg === null) {
+ parameters.push(null);
+ buffers.push(undefined);
+ } else {
+ throw new TypeError(
+ "Invalid ffi arg value, expected TypedArray, UnsafePointer or null",
+ );
+ }
+ } else {
+ parameters.push(arg);
+ }
+ }
+
+ return { parameters, buffers };
+ }
+
+ class UnsafeFnPointer {
+ pointer;
+ definition;
+
+ constructor(pointer, definition) {
+ this.pointer = pointer;
+ this.definition = definition;
+ }
+
+ call(...args) {
+ const { parameters, buffers } = prepareArgs(
+ this.definition.parameters,
+ args,
+ );
+ if (this.definition.nonblocking) {
+ const promise = core.opAsync("op_ffi_call_ptr_nonblocking", {
+ pointer: packU64(this.pointer.value),
+ def: this.definition,
+ parameters,
+ buffers,
+ });
+
+ if (this.definition.result === "pointer") {
+ return promise.then((value) => new UnsafePointer(unpackU64(value)));
+ }
+
+ return promise;
+ } else {
+ const result = core.opSync("op_ffi_call_ptr", {
+ pointer: packU64(this.pointer.value),
+ def: this.definition,
+ parameters,
+ buffers,
+ });
+
+ if (this.definition.result === "pointer") {
+ return new UnsafePointer(unpackU64(result));
+ }
+
+ return result;
+ }
+ }
+ }
+
class DynamicLibrary {
#rid;
symbols = {};
@@ -154,35 +232,7 @@
const types = symbols[symbol].parameters;
this.symbols[symbol] = (...args) => {
- const parameters = [];
- const buffers = [];
-
- for (let i = 0; i < types.length; i++) {
- const type = types[i];
- const arg = args[i];
-
- if (type === "pointer") {
- if (
- arg?.buffer instanceof ArrayBuffer &&
- arg.byteLength !== undefined
- ) {
- parameters.push(buffers.length);
- buffers.push(arg);
- } else if (arg instanceof UnsafePointer) {
- parameters.push(packU64(arg.value));
- buffers.push(undefined);
- } else if (arg === null) {
- parameters.push(null);
- buffers.push(undefined);
- } else {
- throw new TypeError(
- "Invalid ffi arg value, expected TypedArray, UnsafePointer or null",
- );
- }
- } else {
- parameters.push(arg);
- }
- }
+ const { parameters, buffers } = prepareArgs(types, args);
if (isNonBlocking) {
const promise = core.opAsync("op_ffi_call_nonblocking", {
@@ -228,5 +278,10 @@
return new DynamicLibrary(pathFromURL(path), symbols);
}
- window.__bootstrap.ffi = { dlopen, UnsafePointer, UnsafePointerView };
+ window.__bootstrap.ffi = {
+ dlopen,
+ UnsafePointer,
+ UnsafePointerView,
+ UnsafeFnPointer,
+ };
})(this);