2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-08-23 12:31:19 -04:00
|
|
|
|
2023-12-11 22:10:33 -05:00
|
|
|
import { assertEquals, assertRejects, assertThrows } from "./test_util.ts";
|
2021-08-23 12:31:19 -04:00
|
|
|
|
2021-11-23 11:45:18 -05:00
|
|
|
Deno.test({ permissions: { ffi: true } }, function dlopenInvalidArguments() {
|
2021-08-23 12:31:19 -04:00
|
|
|
const filename = "/usr/lib/libc.so.6";
|
|
|
|
assertThrows(() => {
|
|
|
|
// @ts-expect-error: ForeignFunction cannot be null
|
|
|
|
Deno.dlopen(filename, { malloc: null });
|
|
|
|
}, TypeError);
|
|
|
|
assertThrows(() => {
|
|
|
|
Deno.dlopen(filename, {
|
|
|
|
// @ts-expect-error: invalid NativeType
|
|
|
|
malloc: { parameters: ["a"], result: "b" },
|
|
|
|
});
|
|
|
|
}, TypeError);
|
|
|
|
assertThrows(() => {
|
|
|
|
// @ts-expect-error: DynamicLibrary symbols cannot be null
|
|
|
|
Deno.dlopen(filename, null);
|
|
|
|
}, TypeError);
|
|
|
|
assertThrows(() => {
|
|
|
|
// @ts-expect-error: require 2 arguments
|
|
|
|
Deno.dlopen(filename);
|
|
|
|
}, TypeError);
|
|
|
|
});
|
2022-03-25 07:29:54 -04:00
|
|
|
|
|
|
|
Deno.test({ permissions: { ffi: false } }, function ffiPermissionDenied() {
|
|
|
|
assertThrows(() => {
|
|
|
|
Deno.dlopen("/usr/lib/libc.so.6", {});
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
const fnptr = new Deno.UnsafeFnPointer(
|
2023-06-26 09:10:27 -04:00
|
|
|
// @ts-expect-error: Not NonNullable but null check is after permissions check.
|
2023-02-22 12:32:38 -05:00
|
|
|
null,
|
2022-03-25 07:29:54 -04:00
|
|
|
{
|
|
|
|
parameters: ["u32", "pointer"],
|
|
|
|
result: "void",
|
|
|
|
} as const,
|
|
|
|
);
|
|
|
|
assertThrows(() => {
|
|
|
|
fnptr.call(123, null);
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
Deno.UnsafePointer.of(new Uint8Array(0));
|
|
|
|
}, Deno.errors.PermissionDenied);
|
2023-02-22 12:32:38 -05:00
|
|
|
const ptrView = new Deno.UnsafePointerView(
|
2023-06-26 09:10:27 -04:00
|
|
|
// @ts-expect-error: Not NonNullable but null check is after permissions check.
|
2023-02-22 12:32:38 -05:00
|
|
|
null,
|
|
|
|
);
|
2022-03-25 07:29:54 -04:00
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.copyInto(new Uint8Array(0));
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getCString();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getUint8();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getInt8();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getUint16();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getInt16();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getUint32();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getInt32();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getFloat32();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
assertThrows(() => {
|
|
|
|
ptrView.getFloat64();
|
|
|
|
}, Deno.errors.PermissionDenied);
|
|
|
|
});
|
2023-10-08 01:02:07 -04:00
|
|
|
|
|
|
|
Deno.test({ permissions: { ffi: true } }, function pointerOf() {
|
|
|
|
const buffer = new ArrayBuffer(1024);
|
|
|
|
const baseAddress = Deno.UnsafePointer.value(Deno.UnsafePointer.of(buffer));
|
|
|
|
const uint8Address = Deno.UnsafePointer.value(
|
|
|
|
Deno.UnsafePointer.of(new Uint8Array(buffer)),
|
|
|
|
);
|
|
|
|
assertEquals(baseAddress, uint8Address);
|
|
|
|
const float64Address = Deno.UnsafePointer.value(
|
|
|
|
Deno.UnsafePointer.of(new Float64Array(buffer)),
|
|
|
|
);
|
|
|
|
assertEquals(baseAddress, float64Address);
|
|
|
|
const uint8AddressOffset = Deno.UnsafePointer.value(
|
|
|
|
Deno.UnsafePointer.of(new Uint8Array(buffer, 100)),
|
|
|
|
);
|
2024-05-29 22:30:11 -04:00
|
|
|
assertEquals(baseAddress + 100n, uint8AddressOffset);
|
2023-10-08 01:02:07 -04:00
|
|
|
const float64AddressOffset = Deno.UnsafePointer.value(
|
|
|
|
Deno.UnsafePointer.of(new Float64Array(buffer, 80)),
|
|
|
|
);
|
2024-05-29 22:30:11 -04:00
|
|
|
assertEquals(baseAddress + 80n, float64AddressOffset);
|
2023-10-08 01:02:07 -04:00
|
|
|
});
|
2023-12-11 22:10:33 -05:00
|
|
|
|
|
|
|
Deno.test({ permissions: { ffi: true } }, function callWithError() {
|
|
|
|
const throwCb = () => {
|
|
|
|
throw new Error("Error");
|
|
|
|
};
|
|
|
|
const cb = new Deno.UnsafeCallback({
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
}, throwCb);
|
|
|
|
const fnPointer = new Deno.UnsafeFnPointer(cb.pointer, {
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
});
|
|
|
|
assertThrows(() => fnPointer.call());
|
|
|
|
cb.close();
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test(
|
|
|
|
{ permissions: { ffi: true }, ignore: true },
|
|
|
|
async function callNonBlockingWithError() {
|
|
|
|
const throwCb = () => {
|
|
|
|
throw new Error("Error");
|
|
|
|
};
|
|
|
|
const cb = new Deno.UnsafeCallback({
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
}, throwCb);
|
|
|
|
const fnPointer = new Deno.UnsafeFnPointer(cb.pointer, {
|
|
|
|
parameters: [],
|
|
|
|
result: "void",
|
|
|
|
nonblocking: true,
|
|
|
|
});
|
|
|
|
// TODO(mmastrac): currently ignored as we do not thread callback exceptions through nonblocking pointers
|
|
|
|
await assertRejects(async () => await fnPointer.call());
|
|
|
|
cb.close();
|
|
|
|
},
|
|
|
|
);
|