2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2023-01-13 02:51:32 -05:00
|
|
|
|
2022-07-09 05:49:20 -04:00
|
|
|
const targetDir = Deno.execPath().replace(/[^\/\\]+$/, "");
|
|
|
|
const [libPrefix, libSuffix] = {
|
|
|
|
darwin: ["lib", "dylib"],
|
|
|
|
linux: ["lib", "so"],
|
|
|
|
windows: ["", "dll"],
|
|
|
|
}[Deno.build.os];
|
|
|
|
const libPath = `${targetDir}/${libPrefix}test_ffi.${libSuffix}`;
|
|
|
|
|
|
|
|
const dylib = Deno.dlopen(
|
|
|
|
libPath,
|
|
|
|
{
|
|
|
|
store_function: {
|
|
|
|
parameters: ["function"],
|
|
|
|
result: "void",
|
|
|
|
},
|
|
|
|
call_stored_function: {
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
},
|
|
|
|
call_stored_function_thread_safe_and_log: {
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
},
|
|
|
|
} as const,
|
|
|
|
);
|
|
|
|
|
2023-02-22 14:09:59 -05:00
|
|
|
let retry = false;
|
2022-07-09 05:49:20 -04:00
|
|
|
const tripleLogCallback = () => {
|
|
|
|
console.log("Sync");
|
2023-02-26 10:34:57 -05:00
|
|
|
queueMicrotask(() => {
|
2022-07-09 05:49:20 -04:00
|
|
|
console.log("Async");
|
|
|
|
callback.unref();
|
|
|
|
});
|
|
|
|
setTimeout(() => {
|
|
|
|
console.log("Timeout");
|
|
|
|
callback.unref();
|
2023-02-22 14:09:59 -05:00
|
|
|
|
|
|
|
if (retry) {
|
|
|
|
// Re-ref and retry the call to make sure re-refing works.
|
|
|
|
console.log("RETRY THREAD SAFE");
|
|
|
|
retry = false;
|
|
|
|
callback.ref();
|
|
|
|
dylib.symbols.call_stored_function_thread_safe_and_log();
|
|
|
|
}
|
2023-03-25 03:18:41 -04:00
|
|
|
}, 100);
|
2022-07-09 05:49:20 -04:00
|
|
|
};
|
|
|
|
|
2023-02-22 14:09:59 -05:00
|
|
|
const callback = Deno.UnsafeCallback.threadSafe(
|
2022-07-09 05:49:20 -04:00
|
|
|
{
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
} as const,
|
|
|
|
tripleLogCallback,
|
|
|
|
);
|
|
|
|
|
|
|
|
// Store function
|
|
|
|
dylib.symbols.store_function(callback.pointer);
|
|
|
|
|
|
|
|
// Synchronous callback logging
|
|
|
|
console.log("SYNCHRONOUS");
|
2023-03-25 03:18:41 -04:00
|
|
|
// This function only calls the callback, and does not log.
|
2022-07-09 05:49:20 -04:00
|
|
|
dylib.symbols.call_stored_function();
|
|
|
|
console.log("STORED_FUNCTION called");
|
|
|
|
|
|
|
|
// Wait to make sure synch logging and async logging
|
2023-03-25 03:18:41 -04:00
|
|
|
await new Promise((res) => setTimeout(res, 200));
|
2022-07-09 05:49:20 -04:00
|
|
|
|
2023-02-26 10:34:57 -05:00
|
|
|
// Ref once to make sure both `queueMicrotask()` and `setTimeout()`
|
2023-02-22 14:09:59 -05:00
|
|
|
// must resolve and unref before isolate exists.
|
|
|
|
// One ref'ing has been done by `threadSafe` constructor.
|
2022-07-09 05:49:20 -04:00
|
|
|
callback.ref();
|
|
|
|
|
|
|
|
console.log("THREAD SAFE");
|
2023-02-22 14:09:59 -05:00
|
|
|
retry = true;
|
2023-03-25 03:18:41 -04:00
|
|
|
// This function calls the callback and logs 'STORED_FUNCTION called'
|
2022-07-09 05:49:20 -04:00
|
|
|
dylib.symbols.call_stored_function_thread_safe_and_log();
|