@hew-lang/sandbox-vm 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -4
- package/cli/test-runner.mjs +4 -1
- package/dist/interpreter/interpreter.d.ts +1 -1
- package/dist/interpreter/interpreter.js +1 -1
- package/dist/interpreter/parity-runner.js +26 -1
- package/dist/interpreter/run-program.d.ts +3 -2
- package/dist/interpreter/run-program.js +5 -3
- package/dist/interpreter/schema-validator.d.ts +9 -4
- package/dist/interpreter/schema-validator.js +15 -49
- package/dist/interpreter/types.d.ts +4 -0
- package/dist/interpreter/v1/browser-directory.d.ts +107 -0
- package/dist/interpreter/v1/browser-directory.js +288 -0
- package/dist/interpreter/v1/calendar.d.ts +4 -0
- package/dist/interpreter/v1/calendar.js +64 -0
- package/dist/interpreter/v1/codecs.js +2 -2
- package/dist/interpreter/v1/exec.d.ts +2 -2
- package/dist/interpreter/v1/exec.js +439 -183
- package/dist/interpreter/v1/instructions.generated.d.ts +1135 -0
- package/dist/interpreter/v1/instructions.generated.js +106 -0
- package/dist/interpreter/v1/package-graph.d.ts +2 -0
- package/dist/interpreter/v1/package-graph.js +729 -0
- package/dist/interpreter/v1/package-validator.generated.d.ts +3 -0
- package/dist/interpreter/v1/package-validator.generated.js +75846 -0
- package/dist/interpreter/v1/package.d.ts +5 -680
- package/dist/interpreter/v1/package.js +0 -12
- package/dist/interpreter/v1/scheduler.d.ts +5 -1
- package/dist/interpreter/v1/scheduler.js +32 -3
- package/dist/interpreter/v1/shims.d.ts +250 -7
- package/dist/interpreter/v1/shims.js +429 -150
- package/dist/interpreter/v1/structural.d.ts +2 -28
- package/dist/interpreter/v1/timestamp.d.ts +7 -0
- package/dist/interpreter/v1/timestamp.js +54 -0
- package/dist/interpreter/v1/validate.d.ts +8 -2
- package/dist/interpreter/v1/validate.js +190 -202
- package/dist/interpreter/v1/value-operations.d.ts +7 -2
- package/dist/interpreter/v1/value-operations.js +13 -6
- package/dist/interpreter/values.d.ts +4 -0
- package/dist/interpreter/values.js +6 -0
- package/dist/interpreter/worker.js +4 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
borrows, cleanup, checked failures, actor protocols and suspension edges.
|
|
6
6
|
|
|
7
7
|
Actors, tasks and pipes use resumable frames on a deterministic scheduler.
|
|
8
|
-
Timers advance virtual time.
|
|
9
|
-
|
|
8
|
+
Timers advance virtual time. Hosts can supply real origin-private filesystem
|
|
9
|
+
(OPFS) directory handles; network and ambient filesystem operations are refused
|
|
10
|
+
before execution. Other missing operations are reported separately as
|
|
10
11
|
`not_implemented`. The loader is the capability admission authority.
|
|
11
12
|
|
|
12
13
|
## Browser API
|
|
@@ -17,16 +18,43 @@ import { runBytecode } from "@hew-lang/sandbox-vm";
|
|
|
17
18
|
|
|
18
19
|
const { diagnostics, bytecode } = JSON.parse(compileToSandboxBytecode(source));
|
|
19
20
|
if (bytecode) {
|
|
20
|
-
const trace = runBytecode(bytecode, {
|
|
21
|
+
const trace = await runBytecode(bytecode, {
|
|
22
|
+
replay: { step_budget: 100000 },
|
|
23
|
+
});
|
|
21
24
|
}
|
|
22
25
|
```
|
|
23
26
|
|
|
24
27
|
Initialize the Wasm compiler using its generated default export before calling
|
|
25
28
|
it. `runProgram(source, stdin)` is also available for existing page bridges;
|
|
26
|
-
install `globalThis.compileToSandboxBytecode` first.
|
|
29
|
+
install `globalThis.compileToSandboxBytecode` first. Both entrypoints return a Promise. The page result includes
|
|
27
30
|
`stdout`, `exit_code`, `diagnostics`, `status`, `sandbox_rejections`,
|
|
28
31
|
`compiler_version` and `hew_version`.
|
|
29
32
|
|
|
33
|
+
To grant filesystem authority, pass only the directories the program needs:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
const trace = await runBytecode(bytecode, {
|
|
37
|
+
directoryRoots: { read: inputDirectory, write: outputDirectory },
|
|
38
|
+
signal: controller.signal,
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Both roots are optional and default to no authority. The handles must belong to
|
|
43
|
+
this origin's OPFS; external picker-backed handles are refused because their
|
|
44
|
+
symlink confinement is not standardized. Existing Hew `fs.open_read_dir(".")`
|
|
45
|
+
and `fs.open_write_dir(".")` acquire the supplied roots. Relative traversal stays
|
|
46
|
+
beneath the current directory owner, including after narrowing with `subdir`.
|
|
47
|
+
Children remain usable after closing a parent. Each `file.write` publishes its
|
|
48
|
+
bytes before it returns, even while the file owner remains open.
|
|
49
|
+
|
|
50
|
+
`AbortSignal` requests cancellation through the source's authored cleanup edges.
|
|
51
|
+
Filesystem acquisition publishes its owner before observing cancellation, as on
|
|
52
|
+
native hosts. An in-progress file operation drains or aborts its browser writer
|
|
53
|
+
before cancellation releases its inputs. Pure execution retains the deterministic
|
|
54
|
+
virtual scheduler and runs until a host wait or completion. Pass the same options
|
|
55
|
+
as the fourth argument to `runProgram(source, stdin, files, options)`; signals are
|
|
56
|
+
for direct calls rather than worker message payloads.
|
|
57
|
+
|
|
30
58
|
A `sandbox_rejected` result includes rejection entries with `category`, `code`,
|
|
31
59
|
`capability`, `message` and `span`. Categories are `native_only`,
|
|
32
60
|
`not_implemented` and `invalid_package`. Compiler errors, language panics,
|
|
@@ -48,6 +76,13 @@ The [package contract](bytecode/package-v1.md) describes the SIR projection.
|
|
|
48
76
|
Source fixtures are compiled by the public compiler and executed to record
|
|
49
77
|
deterministic traces. Tests also compare executable sources with native Hew.
|
|
50
78
|
|
|
79
|
+
With `hew-wasm/pkg` and `hew-sandbox-vm/dist` built, serve the repository on
|
|
80
|
+
localhost and open `hew-sandbox-vm/test/browser/directory-handles.html` to run the
|
|
81
|
+
real browser filesystem controls. They compile the ordinary Hew source fixture,
|
|
82
|
+
use a temporary OPFS directory, verify disk contents, confinement and cancellation,
|
|
83
|
+
then remove their entries. The page accepts a `compiler` module URL query parameter
|
|
84
|
+
to reuse another built compiler package.
|
|
85
|
+
|
|
51
86
|
`RunOptions.argv` supplies process arguments, including the executable name at
|
|
52
87
|
index zero. It defaults to `["main.hew"]` and is copied for each run. For example,
|
|
53
88
|
`runBytecode(bytecode, { argv: ["greet", "--", "Zoë", ""] })` supplies those exact
|
|
@@ -58,3 +93,7 @@ Pass its initialized `executeCodec` export as `runBytecode`'s `codecBridge`
|
|
|
58
93
|
option. The Node test host loads that package automatically; in a source
|
|
59
94
|
checkout, run `make wasm` to build `hew-wasm/pkg` first. An explicit
|
|
60
95
|
`HEW_WASM_MODULE` module URL can select another build of the same package.
|
|
96
|
+
|
|
97
|
+
UTC calendar operations also require the initialized `executeCalendar`
|
|
98
|
+
export as `calendarBridge`. Both hosts use the shared Chrono calendar engine;
|
|
99
|
+
the bridge preserves integer seconds and nanoseconds exactly.
|
package/cli/test-runner.mjs
CHANGED
|
@@ -22,6 +22,7 @@ try {
|
|
|
22
22
|
const args = parseArgs(process.argv.slice(2));
|
|
23
23
|
const packageValue = JSON.parse(fs.readFileSync(args.path, "utf8"));
|
|
24
24
|
let codecBridge;
|
|
25
|
+
let calendarBridge;
|
|
25
26
|
if (packageValue.codecs?.length) {
|
|
26
27
|
const local = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../hew-wasm/pkg/hew_wasm.js");
|
|
27
28
|
const location = process.env.HEW_WASM_MODULE ?? (fs.existsSync(local) ? pathToFileURL(local).href : "@hew-lang/wasm");
|
|
@@ -31,11 +32,13 @@ try {
|
|
|
31
32
|
await wasm.default({ module_or_path: fs.readFileSync(new URL(resolved.replace(/\.js$/, "_bg.wasm"))) });
|
|
32
33
|
}
|
|
33
34
|
codecBridge = wasm.executeCodec ?? wasm.default?.executeCodec;
|
|
35
|
+
calendarBridge = wasm.executeCalendar ?? wasm.default?.executeCalendar;
|
|
34
36
|
if (typeof codecBridge !== "function") throw new Error("hew-wasm executeCodec export is missing; rebuild the Wasm package");
|
|
35
37
|
}
|
|
36
38
|
const propertyPath = reportPath ? path.join(path.dirname(reportPath), "property.cbor") : null;
|
|
37
|
-
const trace = runBytecode(packageValue, {
|
|
39
|
+
const trace = await runBytecode(packageValue, {
|
|
38
40
|
codecBridge,
|
|
41
|
+
calendarBridge,
|
|
39
42
|
propertyInput: propertyPath && fs.existsSync(propertyPath) ? [...fs.readFileSync(propertyPath)] : [],
|
|
40
43
|
fixtureId: "hew-test",
|
|
41
44
|
traceId: "trace:hew-test",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { RunOptions, SandboxTrace } from "./types.js";
|
|
2
|
-
export declare function runBytecode(input: unknown, options?: RunOptions): SandboxTrace
|
|
2
|
+
export declare function runBytecode(input: unknown, options?: RunOptions): Promise<SandboxTrace>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { validateBytecodePackage } from "./schema-validator.js";
|
|
2
2
|
import { runPackageV1 } from "./v1/exec.js";
|
|
3
3
|
import { TraceBuilder } from "./trace.js";
|
|
4
|
-
export function runBytecode(input, options = {}) {
|
|
4
|
+
export async function runBytecode(input, options = {}) {
|
|
5
5
|
let bytecode;
|
|
6
6
|
try {
|
|
7
7
|
bytecode = validateBytecodePackage(input);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import process from "node:process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
5
|
import { runBytecode } from "./index.js";
|
|
4
6
|
const DEFAULT_SEED = 42;
|
|
5
7
|
const DEFAULT_STEP_BUDGET = 1_000_000;
|
|
@@ -45,7 +47,30 @@ function parseArgs(argv) {
|
|
|
45
47
|
try {
|
|
46
48
|
const args = parseArgs(process.argv.slice(2));
|
|
47
49
|
const bytecode = JSON.parse(fs.readFileSync(args.bytecodePath, "utf8"));
|
|
48
|
-
|
|
50
|
+
let codecBridge;
|
|
51
|
+
if (typeof bytecode === "object" &&
|
|
52
|
+
bytecode !== null &&
|
|
53
|
+
"codecs" in bytecode &&
|
|
54
|
+
Array.isArray(bytecode.codecs) &&
|
|
55
|
+
bytecode.codecs.length) {
|
|
56
|
+
const local = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../../hew-wasm/pkg/hew_wasm.js");
|
|
57
|
+
const location = process.env.HEW_WASM_MODULE ?? pathToFileURL(local).href;
|
|
58
|
+
const wasm = await import(location);
|
|
59
|
+
if (typeof wasm.default === "function") {
|
|
60
|
+
const resolved = location.startsWith("file:")
|
|
61
|
+
? location
|
|
62
|
+
: import.meta.resolve(location);
|
|
63
|
+
await wasm.default({
|
|
64
|
+
module_or_path: fs.readFileSync(new URL(resolved.replace(/\.js$/, "_bg.wasm"))),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
codecBridge = wasm.executeCodec ?? wasm.default?.executeCodec;
|
|
68
|
+
if (typeof codecBridge !== "function") {
|
|
69
|
+
throw new Error("hew-wasm executeCodec export is missing; supply a compatible HEW_WASM_MODULE");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const trace = await runBytecode(bytecode, {
|
|
73
|
+
codecBridge,
|
|
49
74
|
replay: {
|
|
50
75
|
seed: args.seed,
|
|
51
76
|
step_budget: DEFAULT_STEP_BUDGET,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PackageV1 } from "./v1/package.js";
|
|
2
|
-
import type { JsonValue, RuntimeStatus, SandboxRejection } from "./types.js";
|
|
2
|
+
import type { RunOptions, JsonValue, RuntimeStatus, SandboxRejection } from "./types.js";
|
|
3
3
|
export interface Diagnostic {
|
|
4
4
|
severity: string;
|
|
5
5
|
phase: string;
|
|
@@ -24,7 +24,8 @@ type SandboxCompiler = (source: string, profile?: string, files?: Map<string, st
|
|
|
24
24
|
declare global {
|
|
25
25
|
var __hewSandboxCompileToSandboxBytecode: SandboxCompiler | undefined;
|
|
26
26
|
var __hewSandboxExecuteCodec: ((request: string) => string) | undefined;
|
|
27
|
+
var __hewSandboxExecuteCalendar: ((request: string) => string) | undefined;
|
|
27
28
|
var compileToSandboxBytecode: SandboxCompiler | undefined;
|
|
28
29
|
}
|
|
29
|
-
export declare function runProgram(source: string, stdin: string, files?: Map<string, string | Uint8Array
|
|
30
|
+
export declare function runProgram(source: string, stdin: string, files?: Map<string, string | Uint8Array>, options?: RunOptions): Promise<RunProgramResult>;
|
|
30
31
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runBytecode } from "./interpreter.js";
|
|
2
2
|
const SANDBOX_PROFILE = "sandbox-vm-export";
|
|
3
|
-
export function runProgram(source, stdin, files) {
|
|
3
|
+
export async function runProgram(source, stdin, files, options = {}) {
|
|
4
4
|
const compileOutput = compileSource(source, files);
|
|
5
5
|
if (hasErrorDiagnostics(compileOutput.diagnostics) ||
|
|
6
6
|
compileOutput.bytecode === null) {
|
|
@@ -15,9 +15,11 @@ export function runProgram(source, stdin, files) {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
const bytecode = compileOutput.bytecode;
|
|
18
|
-
const trace = runBytecode(bytecode, {
|
|
18
|
+
const trace = await runBytecode(bytecode, {
|
|
19
|
+
...options,
|
|
19
20
|
fixtureId: "page-run",
|
|
20
|
-
codecBridge: globalThis.__hewSandboxExecuteCodec,
|
|
21
|
+
codecBridge: options.codecBridge ?? globalThis.__hewSandboxExecuteCodec,
|
|
22
|
+
calendarBridge: options.calendarBridge ?? globalThis.__hewSandboxExecuteCalendar,
|
|
21
23
|
traceId: "trace:page-run",
|
|
22
24
|
replay: { inputs: [{ kind: "stdin", data: stdin }] },
|
|
23
25
|
});
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PackageV1 } from "./v1/package.js";
|
|
2
|
+
declare const checkedPackage: unique symbol;
|
|
3
|
+
export type CheckedPackage = PackageV1 & {
|
|
4
|
+
readonly [checkedPackage]: true;
|
|
5
|
+
};
|
|
2
6
|
export declare class BytecodeValidationError extends Error {
|
|
3
7
|
readonly errors: string[];
|
|
4
8
|
constructor(errors: string[]);
|
|
5
9
|
}
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
export declare function validateBytecodePackage(input: unknown):
|
|
10
|
+
/** Decode an isolated package before capability admission or any host effect.
|
|
11
|
+
* Cloning prevents a caller or host callback from changing the checked input. */
|
|
12
|
+
export declare function validateBytecodePackage(input: unknown): CheckedPackage;
|
|
13
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validPackage } from "./v1/package-validator.generated.js";
|
|
2
|
+
import { validatePackageGraph } from "./v1/package-graph.js";
|
|
2
3
|
export class BytecodeValidationError extends Error {
|
|
3
4
|
errors;
|
|
4
5
|
constructor(errors) {
|
|
@@ -7,55 +8,20 @@ export class BytecodeValidationError extends Error {
|
|
|
7
8
|
this.name = "BytecodeValidationError";
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
11
|
+
/** Decode an isolated package before capability admission or any host effect.
|
|
12
|
+
* Cloning prevents a caller or host callback from changing the checked input. */
|
|
12
13
|
export function validateBytecodePackage(input) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
errors.push(`${key} must be a string`);
|
|
19
|
-
}
|
|
20
|
-
for (const key of [
|
|
21
|
-
"functions",
|
|
22
|
-
"strings",
|
|
23
|
-
"bytes",
|
|
24
|
-
"regex_patterns",
|
|
25
|
-
"aggregates",
|
|
26
|
-
"variants",
|
|
27
|
-
"runtime_families",
|
|
28
|
-
"externs",
|
|
29
|
-
"suspend_kinds",
|
|
30
|
-
"value_capabilities",
|
|
31
|
-
"closures",
|
|
32
|
-
"vtables",
|
|
33
|
-
]) {
|
|
34
|
-
if (!Array.isArray(input[key]))
|
|
35
|
-
errors.push(`${key} must be an array`);
|
|
36
|
-
}
|
|
37
|
-
if (errors.length)
|
|
38
|
-
throw new BytecodeValidationError(errors);
|
|
39
|
-
for (const fn of input.functions) {
|
|
40
|
-
if (!fn ||
|
|
41
|
-
!Number.isInteger(fn.id) ||
|
|
42
|
-
!Array.isArray(fn.params) ||
|
|
43
|
-
!Array.isArray(fn.places) ||
|
|
44
|
-
!Array.isArray(fn.blocks)) {
|
|
45
|
-
errors.push("malformed function");
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
for (const block of fn.blocks) {
|
|
49
|
-
if (!block ||
|
|
50
|
-
!Number.isInteger(block.id) ||
|
|
51
|
-
!Array.isArray(block.params) ||
|
|
52
|
-
!Array.isArray(block.ops) ||
|
|
53
|
-
!block.term ||
|
|
54
|
-
typeof block.term.op !== "string")
|
|
55
|
-
errors.push("malformed block");
|
|
14
|
+
try {
|
|
15
|
+
const decoded = structuredClone(input);
|
|
16
|
+
if (!validPackage(decoded)) {
|
|
17
|
+
const reasons = (validPackage.errors ?? []).map((issue) => `${issue.instancePath || "/"} ${issue.message ?? "invalid value"}`);
|
|
18
|
+
throw new Error(reasons.join("; ") || "malformed sandbox bytecode package");
|
|
56
19
|
}
|
|
20
|
+
const pkg = decoded;
|
|
21
|
+
validatePackageGraph(pkg);
|
|
22
|
+
return pkg;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new BytecodeValidationError([String(error)]);
|
|
57
26
|
}
|
|
58
|
-
if (errors.length)
|
|
59
|
-
throw new BytecodeValidationError(errors);
|
|
60
|
-
return input;
|
|
61
27
|
}
|
|
@@ -117,9 +117,13 @@ export interface SandboxTrace {
|
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
export interface RunOptions {
|
|
120
|
+
/** Explicit browser filesystem authority; absent roots grant no access. */
|
|
121
|
+
directoryRoots?: import("./v1/browser-directory.js").DirectoryRoots;
|
|
122
|
+
signal?: AbortSignal;
|
|
120
123
|
/** Supplied process arguments including argv[0]. Defaults to ["main.hew"]. */
|
|
121
124
|
argv?: readonly string[];
|
|
122
125
|
codecBridge?: (request: string) => string;
|
|
126
|
+
calendarBridge?: (request: string) => string;
|
|
123
127
|
propertyInput?: number[];
|
|
124
128
|
fixtureId?: string;
|
|
125
129
|
traceId?: string;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type VmValue } from "../values.js";
|
|
2
|
+
/** Authority comes only from the embedding host, never from a path or cwd. */
|
|
3
|
+
export interface DirectoryRoots {
|
|
4
|
+
read?: FileSystemDirectoryHandle;
|
|
5
|
+
write?: FileSystemDirectoryHandle;
|
|
6
|
+
}
|
|
7
|
+
export type BrowserFileOwner = {
|
|
8
|
+
access: "read" | "write";
|
|
9
|
+
handle: FileSystemFileHandle | null;
|
|
10
|
+
cursor: number;
|
|
11
|
+
closed: boolean;
|
|
12
|
+
tail: Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export type BrowserDirectoryOwner = {
|
|
15
|
+
access: "read" | "write";
|
|
16
|
+
handle: FileSystemDirectoryHandle | null;
|
|
17
|
+
closed: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type BrowserFsOwner = BrowserFileOwner | BrowserDirectoryOwner;
|
|
20
|
+
export interface BrowserIoError {
|
|
21
|
+
kind: number;
|
|
22
|
+
message: string;
|
|
23
|
+
}
|
|
24
|
+
export interface BrowserIoResult {
|
|
25
|
+
value: VmValue;
|
|
26
|
+
error: BrowserIoError | null;
|
|
27
|
+
}
|
|
28
|
+
export declare const DIRECTORY_OPERATIONS: {
|
|
29
|
+
readonly hew_dir_open_read: {
|
|
30
|
+
readonly release: "hew_dir_read_close";
|
|
31
|
+
readonly action: "root";
|
|
32
|
+
readonly access: "read";
|
|
33
|
+
};
|
|
34
|
+
readonly hew_dir_open_write: {
|
|
35
|
+
readonly release: "hew_dir_write_close";
|
|
36
|
+
readonly action: "root";
|
|
37
|
+
readonly access: "write";
|
|
38
|
+
};
|
|
39
|
+
readonly hew_dir_read_subdir: {
|
|
40
|
+
readonly release: "hew_dir_read_close";
|
|
41
|
+
readonly action: "subdir";
|
|
42
|
+
readonly access: "read";
|
|
43
|
+
};
|
|
44
|
+
readonly hew_dir_write_subdir: {
|
|
45
|
+
readonly release: "hew_dir_write_close";
|
|
46
|
+
readonly action: "subdir";
|
|
47
|
+
readonly access: "write";
|
|
48
|
+
};
|
|
49
|
+
readonly hew_dir_read_open_file: {
|
|
50
|
+
readonly release: "hew_file_read_close";
|
|
51
|
+
readonly action: "file";
|
|
52
|
+
readonly access: "read";
|
|
53
|
+
};
|
|
54
|
+
readonly hew_dir_write_open_file: {
|
|
55
|
+
readonly release: "hew_file_write_close";
|
|
56
|
+
readonly action: "file";
|
|
57
|
+
readonly access: "write";
|
|
58
|
+
};
|
|
59
|
+
readonly hew_dir_read_is_valid: {
|
|
60
|
+
readonly action: "valid";
|
|
61
|
+
readonly access: "read";
|
|
62
|
+
};
|
|
63
|
+
readonly hew_dir_write_is_valid: {
|
|
64
|
+
readonly action: "valid";
|
|
65
|
+
readonly access: "write";
|
|
66
|
+
};
|
|
67
|
+
readonly hew_file_read_is_valid: {
|
|
68
|
+
readonly action: "valid";
|
|
69
|
+
readonly access: "read";
|
|
70
|
+
};
|
|
71
|
+
readonly hew_file_write_is_valid: {
|
|
72
|
+
readonly action: "valid";
|
|
73
|
+
readonly access: "write";
|
|
74
|
+
};
|
|
75
|
+
readonly hew_dir_read_close: {
|
|
76
|
+
readonly action: "close";
|
|
77
|
+
readonly access: "read";
|
|
78
|
+
};
|
|
79
|
+
readonly hew_dir_write_close: {
|
|
80
|
+
readonly action: "close";
|
|
81
|
+
readonly access: "write";
|
|
82
|
+
};
|
|
83
|
+
readonly hew_file_read_close: {
|
|
84
|
+
readonly action: "close";
|
|
85
|
+
readonly access: "read";
|
|
86
|
+
};
|
|
87
|
+
readonly hew_file_write_close: {
|
|
88
|
+
readonly action: "close";
|
|
89
|
+
readonly access: "write";
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
export type DirectoryOperation = (typeof DIRECTORY_OPERATIONS)[keyof typeof DIRECTORY_OPERATIONS];
|
|
93
|
+
export declare class BrowserDirectories {
|
|
94
|
+
private readonly roots;
|
|
95
|
+
private readonly owners;
|
|
96
|
+
retire(release: (value: Extract<VmValue, {
|
|
97
|
+
kind: "host_resource";
|
|
98
|
+
}>) => void): void;
|
|
99
|
+
/** OPFS has no symlink entries. Picker-backed filesystem link confinement is
|
|
100
|
+
* not standardized, so this adapter refuses those handles before execution. */
|
|
101
|
+
static admission(roots: DirectoryRoots | undefined): Promise<string | null>;
|
|
102
|
+
constructor(roots?: DirectoryRoots);
|
|
103
|
+
call(operation: DirectoryOperation, args: VmValue[], resource?: number | null): VmValue | Promise<BrowserIoResult>;
|
|
104
|
+
private acquire;
|
|
105
|
+
private owned;
|
|
106
|
+
io(operation: "FileRead" | "FileWrite", args: VmValue[], cancelled: () => boolean): Promise<BrowserIoResult>;
|
|
107
|
+
}
|