@poe-platform/safe-js 0.1.799 → 0.1.801
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 +4 -2
- package/dist/safe-js/chunks/{chunk-KULEMOAE.js → chunk-4KMUWNZD.js} +5 -156
- package/dist/safe-js/chunks/{chunk-ULPZIHB5.js → chunk-5RLD4TVI.js} +174 -127
- package/dist/safe-js/chunks/{chunk-MCFRB5X3.js → chunk-6H5VC5W5.js} +84 -14
- package/dist/safe-js/chunks/{chunk-TBZILU4U.js → chunk-7THYP46K.js} +1 -1
- package/dist/safe-js/chunks/{chunk-UU4T2KIT.js → chunk-CK3YK2EC.js} +1 -1
- package/dist/safe-js/chunks/{chunk-3O7HA6WT.js → chunk-F6Y734YA.js} +2 -2
- package/dist/safe-js/chunks/{chunk-M6S3F3WM.js → chunk-HFRBLE6Y.js} +42 -36
- package/dist/safe-js/chunks/{chunk-OPYN6N5M.js → chunk-HPHCQNFV.js} +154 -1
- package/dist/safe-js/chunks/{chunk-W6C3Q6U4.js → chunk-IB6WAQAE.js} +2 -2
- package/dist/safe-js/chunks/{chunk-ZKLJW27N.js → chunk-PMOXSLM5.js} +1 -1
- package/dist/safe-js/chunks/chunk-QRWRR6IA.js +78 -0
- package/dist/safe-js/chunks/{chunk-MDJ7MJYI.js → chunk-XOMGWE37.js} +2 -2
- package/dist/safe-js/chunks/{chunk-QTCPJ7FN.js → chunk-XV5OYKND.js} +1 -1
- package/dist/safe-js/chunks/{chunk-OTVZWRYE.js → chunk-YCFOANSU.js} +23 -18
- package/dist/safe-js/chunks/{cli-runtime-DYXJZCGV.js → cli-runtime-L4IABN2W.js} +15 -15
- package/dist/safe-js/chunks/{dump-XDJEF2LG.js → dump-KUPBSXSL.js} +2 -2
- package/dist/safe-js/chunks/{harness-32OOFC5A.js → harness-3DDUS3RY.js} +2 -2
- package/dist/safe-js/chunks/{mcp-PTCA53MN.js → mcp-5TMFK3UE.js} +3 -3
- package/dist/safe-js/chunks/{migration-file-EEGIOHQB.js → migration-file-4CYSJ6LO.js} +3 -3
- package/dist/safe-js/chunks/{restore-U3CCH36B.js → restore-GDHBT5ZD.js} +3 -3
- package/dist/safe-js/chunks/{run-Q74MU3QQ.js → run-M6N5KCPF.js} +5 -5
- package/dist/safe-js/chunks/{runtime-modules-SL5D6LAJ.js → runtime-modules-MGSXY4BN.js} +2 -2
- package/dist/safe-js/cli.js +2 -2
- package/dist/safe-js/core.d.ts +6 -0
- package/dist/safe-js/core.js +33 -7
- package/dist/safe-js/index.js +24 -93
- package/dist/safe-js/interp/data-copy.d.ts +3 -2
- package/dist/safe-js/interp/host-bridge.d.ts +5 -4
- package/dist/safe-js/modules/fs-config.d.ts +1 -0
- package/dist/safe-js/modules/fs.d.ts +2 -0
- package/dist/safe-js/modules/fs.js +2 -2
- package/dist/safe-js/node-unavailable.d.ts +1 -0
- package/dist/safe-js/portable/chunks/chunk-2FNMGWDK.js +58703 -0
- package/dist/safe-js/portable/chunks/chunk-H5X3T5VP.js +909 -0
- package/dist/safe-js/portable/chunks/chunk-XCTU25SU.js +111 -0
- package/dist/safe-js/portable/chunks/source-files-CVU252FB.js +7 -0
- package/dist/safe-js/portable/core.js +14763 -0
- package/dist/safe-js/portable/modules/fs.js +9 -0
- package/dist/safe-js/snapshot/arguments.d.ts +2 -0
- package/dist/safe-js/snapshot/property-descriptors.d.ts +2 -0
- package/dist/safe-js/snapshot/regexp-properties.d.ts +2 -0
- package/dist/safe-js/snapshot/symbols.d.ts +2 -0
- package/dist/safe-js/workerd.d.ts +3 -0
- package/dist/safe-js/workerd.js +74436 -0
- package/package.json +30 -6
|
@@ -3686,11 +3686,11 @@ function copyBoundedOAuthJson(value, message) {
|
|
|
3686
3686
|
import http from "node:http";
|
|
3687
3687
|
|
|
3688
3688
|
// packages/mcp-oauth/src/client/authorization-state.ts
|
|
3689
|
-
import
|
|
3689
|
+
import crypto2 from "node:crypto";
|
|
3690
3690
|
function createAuthorizationState(input) {
|
|
3691
3691
|
const payload = {
|
|
3692
3692
|
v: 1,
|
|
3693
|
-
n:
|
|
3693
|
+
n: crypto2.randomBytes(16).toString("base64url"),
|
|
3694
3694
|
i: input.issuer,
|
|
3695
3695
|
r: input.requireIssuer
|
|
3696
3696
|
};
|
|
@@ -3753,6 +3753,7 @@ function snapshotLoopbackAuthorizationOptions(options) {
|
|
|
3753
3753
|
...options,
|
|
3754
3754
|
openBrowser: options.openBrowser?.bind(options),
|
|
3755
3755
|
readLine: options.readLine?.bind(options),
|
|
3756
|
+
waitForCallback: options.waitForCallback?.bind(options),
|
|
3756
3757
|
createServer: options.createServer?.bind(options),
|
|
3757
3758
|
callbackPath: options.callbackPath,
|
|
3758
3759
|
redirectUri: options.redirectUri,
|
|
@@ -3767,6 +3768,7 @@ async function createLoopbackAuthorizationSession(options = {}) {
|
|
|
3767
3768
|
const timeoutMs = options.timeoutMs ?? 12e4;
|
|
3768
3769
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647)
|
|
3769
3770
|
throw new Error("OAuth authorization timeoutMs must be a positive supported timer interval");
|
|
3771
|
+
if (options.waitForCallback !== void 0) return createHostedAuthorizationSession(options, timeoutMs);
|
|
3770
3772
|
const target = loopbackTarget(options);
|
|
3771
3773
|
const server = options.createServer ? options.createServer() : http.createServer();
|
|
3772
3774
|
const controller = new AbortController();
|
|
@@ -3829,6 +3831,72 @@ function loopbackTarget(options) {
|
|
|
3829
3831
|
throw new Error("Invalid OAuth loopback callback path");
|
|
3830
3832
|
return { port: 0, host: "127.0.0.1", callbackPath };
|
|
3831
3833
|
}
|
|
3834
|
+
function validateAuthorizationRedirect(options) {
|
|
3835
|
+
if (options.waitForCallback === void 0) {
|
|
3836
|
+
loopbackTarget(options);
|
|
3837
|
+
return;
|
|
3838
|
+
}
|
|
3839
|
+
if (typeof options.waitForCallback !== "function" || options.redirectUri === void 0)
|
|
3840
|
+
throw new Error("Hosted OAuth callbacks require redirectUri and waitForCallback");
|
|
3841
|
+
validateHostedOAuthRedirect(options.redirectUri, options.callbackPath);
|
|
3842
|
+
}
|
|
3843
|
+
function validateHostedOAuthRedirect(redirectUri, callbackPath) {
|
|
3844
|
+
const url = new URL(redirectUri);
|
|
3845
|
+
if (url.protocol !== "https:" || url.username || url.password || url.href.includes("#") || url.port === "0" || oauthCallbackParameters.some((name) => url.searchParams.has(name)) || [...redirectUri].some((char) => char.codePointAt(0) <= 32) || callbackPath !== void 0 && callbackPath !== url.pathname)
|
|
3846
|
+
throw new Error("Invalid hosted OAuth redirect URI");
|
|
3847
|
+
}
|
|
3848
|
+
function createHostedAuthorizationSession(options, timeoutMs) {
|
|
3849
|
+
validateAuthorizationRedirect(options);
|
|
3850
|
+
const redirectUri = options.redirectUri, controller = new AbortController();
|
|
3851
|
+
let used = false;
|
|
3852
|
+
const aborted = () => controller.abort(options.signal?.reason);
|
|
3853
|
+
const timer = setTimeout(() => controller.abort(new Error("OAuth authorization timed out")), timeoutMs);
|
|
3854
|
+
timer.unref?.();
|
|
3855
|
+
const cleanup = () => {
|
|
3856
|
+
clearTimeout(timer);
|
|
3857
|
+
options.signal?.removeEventListener("abort", aborted);
|
|
3858
|
+
};
|
|
3859
|
+
controller.signal.addEventListener("abort", cleanup, { once: true });
|
|
3860
|
+
options.signal?.addEventListener("abort", aborted, { once: true });
|
|
3861
|
+
if (options.signal?.aborted) aborted();
|
|
3862
|
+
return {
|
|
3863
|
+
redirectUri,
|
|
3864
|
+
async waitForCode(authorizationUrl) {
|
|
3865
|
+
controller.signal.throwIfAborted();
|
|
3866
|
+
if (used) throw new Error("OAuth authorization session has already been used");
|
|
3867
|
+
used = true;
|
|
3868
|
+
try {
|
|
3869
|
+
const authorization = new URL(authorizationUrl);
|
|
3870
|
+
if (authorization.searchParams.getAll("redirect_uri").length !== 1 || authorization.searchParams.get("redirect_uri") !== redirectUri)
|
|
3871
|
+
throw new Error("OAuth authorization redirect mismatch");
|
|
3872
|
+
const callback = await new Promise((resolve, reject) => {
|
|
3873
|
+
const onAbort = () => reject(controller.signal.reason);
|
|
3874
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
3875
|
+
void Promise.resolve().then(() => {
|
|
3876
|
+
controller.signal.throwIfAborted();
|
|
3877
|
+
return options.waitForCallback({ authorizationUrl, redirectUri, signal: controller.signal });
|
|
3878
|
+
}).then(resolve, reject).finally(() => controller.signal.removeEventListener("abort", onAbort));
|
|
3879
|
+
});
|
|
3880
|
+
controller.signal.throwIfAborted();
|
|
3881
|
+
const url = new URL(callback), base = new URL(redirectUri);
|
|
3882
|
+
if (url.origin !== base.origin || url.pathname !== base.pathname || url.username || url.password || url.href.includes("#") || [...callback].some((char) => char.codePointAt(0) <= 32)) throw new Error("OAuth callback redirect mismatch");
|
|
3883
|
+
const params = readAuthorizationCallbackParameters(url);
|
|
3884
|
+
for (const name of oauthCallbackParameters) url.searchParams.delete(name);
|
|
3885
|
+
if (url.searchParams.toString() !== base.searchParams.toString()) throw new Error("OAuth callback redirect mismatch");
|
|
3886
|
+
const expected = readExpectedAuthorizationCallback(authorizationUrl);
|
|
3887
|
+
if (expected.state === null) throw new Error("OAuth authorization missing state");
|
|
3888
|
+
validateAuthorizationCallbackBinding(params, expected);
|
|
3889
|
+
if (params.error !== null) throw new OAuthAuthorizationError(params.error, params.errorDescription ?? params.error);
|
|
3890
|
+
return validateAuthorizationCallbackParameters(params, expected);
|
|
3891
|
+
} finally {
|
|
3892
|
+
controller.abort(new Error("OAuth authorization session closed"));
|
|
3893
|
+
}
|
|
3894
|
+
},
|
|
3895
|
+
close() {
|
|
3896
|
+
controller.abort(new Error("OAuth authorization session closed"));
|
|
3897
|
+
}
|
|
3898
|
+
};
|
|
3899
|
+
}
|
|
3832
3900
|
async function startServer(server, port, host, signal) {
|
|
3833
3901
|
signal.throwIfAborted();
|
|
3834
3902
|
return new Promise((resolve, reject) => {
|
|
@@ -4076,7 +4144,9 @@ function normalizeStoredOAuthClient(value) {
|
|
|
4076
4144
|
if (requestedRedirectUri !== void 0) {
|
|
4077
4145
|
try {
|
|
4078
4146
|
if (typeof requestedRedirectUri !== "string") throw new Error("Invalid redirect identity");
|
|
4079
|
-
|
|
4147
|
+
if (new URL(requestedRedirectUri).protocol === "https:")
|
|
4148
|
+
validateHostedOAuthRedirect(requestedRedirectUri);
|
|
4149
|
+
else loopbackTarget({ redirectUri: requestedRedirectUri });
|
|
4080
4150
|
} catch {
|
|
4081
4151
|
throw new Error("Invalid stored OAuth registration redirect identity");
|
|
4082
4152
|
}
|
|
@@ -4128,7 +4198,7 @@ function registrationMatchesRedirect(client, requestedUri, fresh = false) {
|
|
|
4128
4198
|
}
|
|
4129
4199
|
|
|
4130
4200
|
// packages/mcp-oauth/src/client/auth-store-session-store.ts
|
|
4131
|
-
import
|
|
4201
|
+
import crypto3 from "node:crypto";
|
|
4132
4202
|
import path4 from "node:path";
|
|
4133
4203
|
|
|
4134
4204
|
// packages/auth-store/src/encrypted-file-store.ts
|
|
@@ -4886,7 +4956,7 @@ function snapshotPersistenceOptions(options) {
|
|
|
4886
4956
|
}
|
|
4887
4957
|
function createNamedSecretStore(key2, options, defaults, namespace) {
|
|
4888
4958
|
options = snapshotOAuthPersistenceOptions(options);
|
|
4889
|
-
const hash =
|
|
4959
|
+
const hash = crypto3.createHash("sha256").update(namespace === void 0 ? key2 : JSON.stringify([namespace, key2])).digest("hex");
|
|
4890
4960
|
const configuredFilePath = options.fileStore?.filePath;
|
|
4891
4961
|
const parsedFilePath = configuredFilePath === void 0 ? null : path4.parse(configuredFilePath);
|
|
4892
4962
|
const fileStore = {
|
|
@@ -4968,7 +5038,7 @@ function isStoredOAuthTokensOrMissing(value) {
|
|
|
4968
5038
|
return false;
|
|
4969
5039
|
}
|
|
4970
5040
|
const scope = getOwnEntry4(value, "scope");
|
|
4971
|
-
return scope === void 0 || typeof scope === "string" && scope.trim().length > 0;
|
|
5041
|
+
return scope === void 0 || scope === "" || typeof scope === "string" && scope.trim().length > 0;
|
|
4972
5042
|
}
|
|
4973
5043
|
function isNonBlankOwnString(record2, key2) {
|
|
4974
5044
|
const value = getOwnString(record2, key2);
|
|
@@ -5186,12 +5256,12 @@ async function fetchMcpResponse(fetchImplementation, input, init = {}) {
|
|
|
5186
5256
|
import { URL as URL2 } from "node:url";
|
|
5187
5257
|
|
|
5188
5258
|
// packages/mcp-oauth/src/client/pkce.ts
|
|
5189
|
-
import
|
|
5259
|
+
import crypto4 from "node:crypto";
|
|
5190
5260
|
function generateCodeVerifier() {
|
|
5191
|
-
return
|
|
5261
|
+
return crypto4.randomBytes(32).toString("base64url");
|
|
5192
5262
|
}
|
|
5193
5263
|
function generateCodeChallenge(verifier) {
|
|
5194
|
-
return
|
|
5264
|
+
return crypto4.createHash("sha256").update(verifier).digest("base64url");
|
|
5195
5265
|
}
|
|
5196
5266
|
|
|
5197
5267
|
// packages/mcp-oauth/src/http-response.ts
|
|
@@ -5320,7 +5390,7 @@ async function requestTokens(input) {
|
|
|
5320
5390
|
if (method === "client_secret_basic") {
|
|
5321
5391
|
const encoded = new URLSearchParams({ credential: input.clientId }).toString().slice("credential=".length);
|
|
5322
5392
|
const encodedSecret = new URLSearchParams({ credential: input.clientSecret }).toString().slice("credential=".length);
|
|
5323
|
-
headers.set("Authorization", `Basic ${
|
|
5393
|
+
headers.set("Authorization", `Basic ${btoa(`${encoded}:${encodedSecret}`)}`);
|
|
5324
5394
|
} else {
|
|
5325
5395
|
body.set("client_id", input.clientId);
|
|
5326
5396
|
if (method === "client_secret_post") body.set("client_secret", input.clientSecret);
|
|
@@ -5368,7 +5438,7 @@ async function requestTokens(input) {
|
|
|
5368
5438
|
throw new Error("OAuth token response has invalid refresh_token");
|
|
5369
5439
|
const scope = getOwnEntry5(payload, "scope");
|
|
5370
5440
|
const normalizedRefreshToken = typeof refreshToken === "string" && refreshToken.trim().length > 0 ? refreshToken.trim() : void 0;
|
|
5371
|
-
const normalizedScope = normalizeOAuthScope(scope);
|
|
5441
|
+
const normalizedScope = scope === "" ? "" : normalizeOAuthScope(scope);
|
|
5372
5442
|
if (scope !== void 0 && normalizedScope === void 0)
|
|
5373
5443
|
throw new Error("Invalid OAuth scope syntax in token response");
|
|
5374
5444
|
return {
|
|
@@ -5494,7 +5564,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
5494
5564
|
const clientMode = options.client.mode;
|
|
5495
5565
|
const interactiveEnabled = options.allowInteractive !== false;
|
|
5496
5566
|
const sessionLockTimeoutMs = options.sessionLockTimeoutMs;
|
|
5497
|
-
|
|
5567
|
+
validateAuthorizationRedirect(browser);
|
|
5498
5568
|
assertPersistenceNamespace(options.persistenceNamespace);
|
|
5499
5569
|
const clientMetadata = getClientMetadata(options.client);
|
|
5500
5570
|
const requestedScope = clientMetadata?.scope;
|
|
@@ -6116,7 +6186,7 @@ function normalizeStoredTokens(value) {
|
|
|
6116
6186
|
const scope = getOwnEntry6(value, "scope");
|
|
6117
6187
|
const normalizedAccessToken = accessToken?.trim();
|
|
6118
6188
|
const normalizedRefreshToken = typeof refreshToken === "string" ? refreshToken.trim() : void 0;
|
|
6119
|
-
const normalizedScope = normalizeOAuthScope(scope);
|
|
6189
|
+
const normalizedScope = scope === "" ? "" : normalizeOAuthScope(scope);
|
|
6120
6190
|
if (accessToken === void 0 || normalizedAccessToken === void 0 || normalizedAccessToken.length === 0 || tokenType !== "Bearer" || !(expiresAt === null || typeof expiresAt === "number" && Number.isSafeInteger(expiresAt) && expiresAt <= MAX_JS_DATE_MS3 && Number.isFinite(new Date(expiresAt).getTime())) || refreshToken !== void 0 && (typeof refreshToken !== "string" || normalizedRefreshToken === void 0 || normalizedRefreshToken.length === 0)) {
|
|
6121
6191
|
return void 0;
|
|
6122
6192
|
}
|
|
@@ -6125,7 +6195,7 @@ function normalizeStoredTokens(value) {
|
|
|
6125
6195
|
tokenType,
|
|
6126
6196
|
expiresAt,
|
|
6127
6197
|
...normalizedRefreshToken === void 0 ? {} : { refreshToken: normalizedRefreshToken },
|
|
6128
|
-
...normalizedScope === void 0
|
|
6198
|
+
...normalizedScope === void 0 ? {} : { scope: normalizedScope }
|
|
6129
6199
|
};
|
|
6130
6200
|
}
|
|
6131
6201
|
function getClientMetadata(client) {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
validateMigrationReconciliation,
|
|
11
11
|
validateMigrationSemantics,
|
|
12
12
|
validateSnapshotMigration
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PMOXSLM5.js";
|
|
14
14
|
import {
|
|
15
15
|
DUMP_FORMAT_VERSION,
|
|
16
16
|
EXECUTION_SEMANTICS,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
serializeSafeJSSnapshot,
|
|
21
21
|
validateDumpEnvelope,
|
|
22
22
|
validateSnapshotData
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-5RLD4TVI.js";
|
|
24
24
|
import {
|
|
25
25
|
parseModule
|
|
26
26
|
} from "./chunk-A3LXCGMJ.js";
|
|
@@ -7,15 +7,15 @@ import {
|
|
|
7
7
|
} from "./chunk-ONWFPHUI.js";
|
|
8
8
|
import {
|
|
9
9
|
restore
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XOMGWE37.js";
|
|
11
11
|
import {
|
|
12
12
|
hashParsedAst,
|
|
13
13
|
hashSource
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-PMOXSLM5.js";
|
|
15
15
|
import {
|
|
16
16
|
attachDumpController,
|
|
17
17
|
createDumpController
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-XV5OYKND.js";
|
|
19
19
|
import {
|
|
20
20
|
DUMP_FORMAT_VERSION,
|
|
21
21
|
EXECUTION_SEMANTICS,
|
|
@@ -107,7 +107,7 @@ import {
|
|
|
107
107
|
wrapCallerInjectedBindings,
|
|
108
108
|
wrapCancelableBindings,
|
|
109
109
|
wrapHostConstructor
|
|
110
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-5RLD4TVI.js";
|
|
111
111
|
import {
|
|
112
112
|
Budget,
|
|
113
113
|
CompileScope,
|
|
@@ -1217,7 +1217,7 @@ var RealmState = class {
|
|
|
1217
1217
|
this.assertOpen();
|
|
1218
1218
|
const closure = readGuestCallback(callback, this);
|
|
1219
1219
|
this.checkCollection(this.pendingCallbacks.size + 1, this.limits.callbacks, "pending callback");
|
|
1220
|
-
const scheduled = this.options.callbackScheduling === "after-prefix";
|
|
1220
|
+
const scheduled = this.options.callbackScheduling === "after-prefix" || this.queuedCallbacks.has(callback);
|
|
1221
1221
|
const record = {
|
|
1222
1222
|
closure,
|
|
1223
1223
|
prefixComplete: false
|
|
@@ -1599,7 +1599,7 @@ var RealmState = class {
|
|
|
1599
1599
|
await this.dispose();
|
|
1600
1600
|
this.assertOpen();
|
|
1601
1601
|
if (this.active !== void 0) throw new SandboxError("reentry");
|
|
1602
|
-
const scheduled = this.options.callbackScheduling === "after-prefix";
|
|
1602
|
+
const scheduled = this.options.callbackScheduling === "after-prefix" || this.releaseReconciliation !== void 0 || this.pendingWork.size > 0;
|
|
1603
1603
|
if (scheduled && (this.phase.getStore()?.active || [...this.pendingCallbacks].some((record) => !record.prefixComplete)))
|
|
1604
1604
|
throw new SandboxError("reentry");
|
|
1605
1605
|
const rejectionOwner = scheduled ? this.tracker.startOperation() : void 0;
|
|
@@ -1649,13 +1649,13 @@ var RealmState = class {
|
|
|
1649
1649
|
} finally {
|
|
1650
1650
|
this.tracker.finishOperation(rejectionOwner);
|
|
1651
1651
|
if (this.active === pending) this.active = void 0;
|
|
1652
|
-
if (scheduled) this.reconcileWhenIdle();
|
|
1652
|
+
if (scheduled || this.releaseReconciliation !== void 0) this.reconcileWhenIdle();
|
|
1653
1653
|
}
|
|
1654
1654
|
}
|
|
1655
1655
|
close = () => {
|
|
1656
1656
|
this.closed = true;
|
|
1657
1657
|
this.controller.abort(new Error("SafeJS realm is closed."));
|
|
1658
|
-
if (this.options.callbackScheduling === "after-prefix") {
|
|
1658
|
+
if (this.options.callbackScheduling === "after-prefix" || this.releaseReconciliation !== void 0 || this.pendingWork.size > 0) {
|
|
1659
1659
|
const disposal = this.dispose();
|
|
1660
1660
|
if (this.phase.getStore()?.active) {
|
|
1661
1661
|
void disposal.catch(() => void 0);
|
|
@@ -1674,7 +1674,7 @@ var RealmState = class {
|
|
|
1674
1674
|
this.closed = true;
|
|
1675
1675
|
this.controller.abort(new Error("SafeJS realm is closed."));
|
|
1676
1676
|
this.options.signal?.removeEventListener("abort", this.abort);
|
|
1677
|
-
if (this.options.callbackScheduling === "after-prefix") {
|
|
1677
|
+
if (this.options.callbackScheduling === "after-prefix" || this.releaseReconciliation !== void 0 || this.pendingWork.size > 0) {
|
|
1678
1678
|
this.disposal = Promise.resolve().then(async () => {
|
|
1679
1679
|
while (this.pendingWork.size > 0) await Promise.allSettled([...this.pendingWork]);
|
|
1680
1680
|
await this.sourceGraph?.settle();
|
|
@@ -1836,16 +1836,24 @@ import { createFsBridge } from "@poe-platform/safe-fs/core";
|
|
|
1836
1836
|
var DEFAULT_WRITE_MAX_ATTEMPTS = 3;
|
|
1837
1837
|
var DEFAULT_WRITE_RETRY_DELAY_MS = 100;
|
|
1838
1838
|
var LOCKED_FILE_ERROR_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
1839
|
-
var
|
|
1839
|
+
var adapterOperations = /* @__PURE__ */ new WeakMap();
|
|
1840
1840
|
var FileSnapshotBackend = class {
|
|
1841
1841
|
constructor(path, options = {}) {
|
|
1842
1842
|
this.path = path;
|
|
1843
|
+
const adapter = options.adapter ?? hostFs;
|
|
1844
|
+
let pending = adapterOperations.get(adapter);
|
|
1845
|
+
if (pending === void 0) {
|
|
1846
|
+
pending = /* @__PURE__ */ new Map();
|
|
1847
|
+
adapterOperations.set(adapter, pending);
|
|
1848
|
+
}
|
|
1849
|
+
this.#pendingOperations = pending;
|
|
1843
1850
|
this.#io = options.adapter === void 0 ? hostFs : createFsBridge(options.adapter, { codec: fsCodec });
|
|
1844
1851
|
this.#writeMaxAttempts = options.writeMaxAttempts ?? DEFAULT_WRITE_MAX_ATTEMPTS;
|
|
1845
1852
|
this.#writeRetryDelayMs = options.writeRetryDelayMs ?? DEFAULT_WRITE_RETRY_DELAY_MS;
|
|
1846
1853
|
}
|
|
1847
1854
|
path;
|
|
1848
1855
|
#io;
|
|
1856
|
+
#pendingOperations;
|
|
1849
1857
|
#writeMaxAttempts;
|
|
1850
1858
|
#writeRetryDelayMs;
|
|
1851
1859
|
async read() {
|
|
@@ -1863,6 +1871,7 @@ var FileSnapshotBackend = class {
|
|
|
1863
1871
|
}
|
|
1864
1872
|
async write(snapshot) {
|
|
1865
1873
|
await enqueueOperation(
|
|
1874
|
+
this.#pendingOperations,
|
|
1866
1875
|
this.path,
|
|
1867
1876
|
() => writeSnapshotAtomically(this.#io, this.path, snapshot, {
|
|
1868
1877
|
maxAttempts: this.#writeMaxAttempts,
|
|
@@ -1871,7 +1880,7 @@ var FileSnapshotBackend = class {
|
|
|
1871
1880
|
);
|
|
1872
1881
|
}
|
|
1873
1882
|
async remove() {
|
|
1874
|
-
await enqueueOperation(this.path, async () => {
|
|
1883
|
+
await enqueueOperation(this.#pendingOperations, this.path, async () => {
|
|
1875
1884
|
try {
|
|
1876
1885
|
await this.#io.unlink(this.path);
|
|
1877
1886
|
} catch (error) {
|
|
@@ -1959,7 +1968,7 @@ async function writeSnapshotOnce(io, temporaryPath, snapshotPath, contents) {
|
|
|
1959
1968
|
}
|
|
1960
1969
|
}
|
|
1961
1970
|
}
|
|
1962
|
-
async function enqueueOperation(path, operation) {
|
|
1971
|
+
async function enqueueOperation(pendingOperations, path, operation) {
|
|
1963
1972
|
const previous = pendingOperations.get(path) ?? Promise.resolve();
|
|
1964
1973
|
const pending = previous.catch(() => void 0).then(operation);
|
|
1965
1974
|
const queued = pending.catch(() => void 0);
|
|
@@ -2551,10 +2560,9 @@ function run(source, options = {}) {
|
|
|
2551
2560
|
migration: restoredSnapshot?.migration,
|
|
2552
2561
|
bindings: executionScope.snapshot().bindings,
|
|
2553
2562
|
clock: options.clock,
|
|
2554
|
-
hostCalls
|
|
2555
|
-
replay: hostCalls.snapshotReplay(),
|
|
2563
|
+
hostCalls,
|
|
2556
2564
|
initialInputs: initialInputs.snapshot,
|
|
2557
|
-
promiseReplay
|
|
2565
|
+
promiseReplay,
|
|
2558
2566
|
random,
|
|
2559
2567
|
sourceHash
|
|
2560
2568
|
});
|
|
@@ -2581,12 +2589,11 @@ function run(source, options = {}) {
|
|
|
2581
2589
|
migration: restoredSnapshot?.migration,
|
|
2582
2590
|
bindings: interpreterSnapshot2.bindings,
|
|
2583
2591
|
clock: options.clock,
|
|
2584
|
-
hostCalls
|
|
2592
|
+
hostCalls,
|
|
2585
2593
|
loopIterations: interpreterSnapshot2.loopIterations,
|
|
2586
2594
|
pendingAwaits: [createPendingAwaitSnapshot(yieldPoint)],
|
|
2587
|
-
replay: hostCalls.snapshotReplay(),
|
|
2588
2595
|
initialInputs: initialInputs.snapshot,
|
|
2589
|
-
promiseReplay
|
|
2596
|
+
promiseReplay,
|
|
2590
2597
|
random,
|
|
2591
2598
|
randomResumeState: typeof yieldPoint.replayState === "number" ? yieldPoint.replayState : void 0,
|
|
2592
2599
|
sourceHash
|
|
@@ -2626,12 +2633,11 @@ function run(source, options = {}) {
|
|
|
2626
2633
|
migration: restoredSnapshot?.migration,
|
|
2627
2634
|
bindings: interpreterSnapshot2.bindings,
|
|
2628
2635
|
clock: options.clock,
|
|
2629
|
-
hostCalls
|
|
2636
|
+
hostCalls,
|
|
2630
2637
|
loopIterations: interpreterSnapshot2.loopIterations,
|
|
2631
2638
|
pendingAwaits: [createPendingAwaitSnapshot(yieldPoint)],
|
|
2632
|
-
replay: hostCalls.snapshotReplay(),
|
|
2633
2639
|
initialInputs: initialInputs.snapshot,
|
|
2634
|
-
promiseReplay
|
|
2640
|
+
promiseReplay,
|
|
2635
2641
|
random,
|
|
2636
2642
|
randomResumeState: typeof yieldPoint.replayState === "number" ? yieldPoint.replayState : void 0,
|
|
2637
2643
|
sourceHash
|
|
@@ -2648,27 +2654,17 @@ function run(source, options = {}) {
|
|
|
2648
2654
|
await throwIfReturnedPromiseRejected(result2);
|
|
2649
2655
|
await throwIfUnhandledPromiseRejected(promiseTracker);
|
|
2650
2656
|
await activeSnapshotScheduler.finish();
|
|
2651
|
-
let replay;
|
|
2652
|
-
let replayError;
|
|
2653
|
-
try {
|
|
2654
|
-
replay = hostCalls.snapshotReplay();
|
|
2655
|
-
} catch (error) {
|
|
2656
|
-
if (!(error instanceof MissingReplayCapabilityError)) throw error;
|
|
2657
|
-
replayError = error.message;
|
|
2658
|
-
}
|
|
2659
2657
|
const snapshot = createRunSnapshot({
|
|
2660
2658
|
executionSemantics,
|
|
2661
2659
|
migration: restoredSnapshot?.migration,
|
|
2662
2660
|
bindings: executionScope.snapshot().bindings,
|
|
2663
2661
|
clock: options.clock,
|
|
2664
|
-
hostCalls
|
|
2665
|
-
replay,
|
|
2662
|
+
hostCalls,
|
|
2666
2663
|
initialInputs: initialInputs.snapshot,
|
|
2667
|
-
promiseReplay
|
|
2664
|
+
promiseReplay,
|
|
2668
2665
|
random,
|
|
2669
2666
|
sourceHash
|
|
2670
2667
|
});
|
|
2671
|
-
if (replayError !== void 0) snapshot.replayError = replayError;
|
|
2672
2668
|
dumpController.finalize(snapshot);
|
|
2673
2669
|
completedSnapshot = snapshot;
|
|
2674
2670
|
reconcileCompiledValues(
|
|
@@ -2845,6 +2841,15 @@ function createExecutableNode(module) {
|
|
|
2845
2841
|
};
|
|
2846
2842
|
}
|
|
2847
2843
|
function createRunSnapshot(input) {
|
|
2844
|
+
let replay;
|
|
2845
|
+
let replayError;
|
|
2846
|
+
try {
|
|
2847
|
+
replay = input.hostCalls.snapshotReplay();
|
|
2848
|
+
} catch (error) {
|
|
2849
|
+
if (!(error instanceof MissingReplayCapabilityError)) throw error;
|
|
2850
|
+
replayError = error.message;
|
|
2851
|
+
}
|
|
2852
|
+
const hostCalls = input.hostCalls.snapshot();
|
|
2848
2853
|
const snapshot = {
|
|
2849
2854
|
version: DUMP_FORMAT_VERSION,
|
|
2850
2855
|
executionSemantics: input.executionSemantics,
|
|
@@ -2852,11 +2857,12 @@ function createRunSnapshot(input) {
|
|
|
2852
2857
|
...input.migration === void 0 ? {} : { migration: structuredClone(input.migration) },
|
|
2853
2858
|
bindings: input.bindings,
|
|
2854
2859
|
clock: input.clock?.snapshot(),
|
|
2855
|
-
...
|
|
2860
|
+
...hostCalls.length === 0 ? {} : { hostCalls },
|
|
2856
2861
|
...input.loopIterations === void 0 ? {} : { loopIterations: input.loopIterations },
|
|
2857
|
-
...
|
|
2862
|
+
...replay === void 0 ? {} : { replay },
|
|
2863
|
+
...replayError === void 0 ? {} : { replayError },
|
|
2858
2864
|
...input.initialInputs === void 0 ? {} : { initialInputs: structuredClone(input.initialInputs) },
|
|
2859
|
-
|
|
2865
|
+
promiseReplay: input.promiseReplay.snapshot(),
|
|
2860
2866
|
...input.pendingAwaits === void 0 || input.pendingAwaits.length === 0 ? {} : { pendingAwaits: input.pendingAwaits },
|
|
2861
2867
|
random: input.random === void 0 ? void 0 : {
|
|
2862
2868
|
seed: input.random.seed,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
collectComments,
|
|
6
6
|
formatParseError,
|
|
7
7
|
hoistedVarDeclarations,
|
|
8
|
+
hostErrorData,
|
|
8
9
|
numericTypedArrayConstructors,
|
|
9
10
|
parseModule,
|
|
10
11
|
tokenize
|
|
@@ -11174,6 +11175,158 @@ function hasOnlyRegexLiteralDiagnostics(diagnostics) {
|
|
|
11174
11175
|
);
|
|
11175
11176
|
}
|
|
11176
11177
|
|
|
11178
|
+
// packages/safe-js/src/modules/env.ts
|
|
11179
|
+
var EnvAccessError = class extends Error {
|
|
11180
|
+
code = "ENV_ACCESS_DENIED";
|
|
11181
|
+
variable;
|
|
11182
|
+
constructor(variable) {
|
|
11183
|
+
super(`Environment access denied for ${JSON.stringify(variable)}.`);
|
|
11184
|
+
this.name = "EnvAccessError";
|
|
11185
|
+
this.variable = variable;
|
|
11186
|
+
hostErrorData.set(this, { code: this.code, variable });
|
|
11187
|
+
}
|
|
11188
|
+
};
|
|
11189
|
+
function makeEnvModule(input) {
|
|
11190
|
+
const options = normalizeEnvOptions(Array.isArray(input) ? { allow: input } : input);
|
|
11191
|
+
const allowedNames = new Set(options.allow);
|
|
11192
|
+
const values = options.values;
|
|
11193
|
+
return {
|
|
11194
|
+
get(name) {
|
|
11195
|
+
const variable = readEnvName(name, "Environment variable name");
|
|
11196
|
+
if (!allowedNames.has(variable)) throw new EnvAccessError(variable);
|
|
11197
|
+
return readEnvValue(values ?? (typeof process !== "undefined" ? process.env ?? {} : {}), variable);
|
|
11198
|
+
}
|
|
11199
|
+
};
|
|
11200
|
+
}
|
|
11201
|
+
function parseEnvConfig(json) {
|
|
11202
|
+
return normalizeEnvOptions(JSON.parse(json));
|
|
11203
|
+
}
|
|
11204
|
+
function normalizeEnvOptions(input) {
|
|
11205
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
11206
|
+
throw new TypeError("Environment options must be an object.");
|
|
11207
|
+
}
|
|
11208
|
+
const fields = Object.getOwnPropertyDescriptors(input);
|
|
11209
|
+
for (const key of Reflect.ownKeys(fields)) {
|
|
11210
|
+
if (key !== "allow" && key !== "values") {
|
|
11211
|
+
throw new TypeError("Unknown environment option.");
|
|
11212
|
+
}
|
|
11213
|
+
if (!("value" in fields[key])) {
|
|
11214
|
+
throw new TypeError("Environment options must not contain accessors.");
|
|
11215
|
+
}
|
|
11216
|
+
}
|
|
11217
|
+
const inputAllow = Object.getOwnPropertyDescriptor(input, "allow")?.value;
|
|
11218
|
+
if (!Array.isArray(inputAllow)) {
|
|
11219
|
+
throw new TypeError("Environment allow list must be an array of non-empty strings.");
|
|
11220
|
+
}
|
|
11221
|
+
const allow = [];
|
|
11222
|
+
for (let index = 0; index < inputAllow.length; index += 1) {
|
|
11223
|
+
const descriptor = Object.getOwnPropertyDescriptor(inputAllow, index);
|
|
11224
|
+
if (descriptor === void 0 || !("value" in descriptor)) {
|
|
11225
|
+
throw new TypeError("Environment allow list must contain only own data entries.");
|
|
11226
|
+
}
|
|
11227
|
+
allow.push(readEnvName(descriptor.value, `Environment allow list[${index}]`));
|
|
11228
|
+
}
|
|
11229
|
+
const inputValues = Object.getOwnPropertyDescriptor(input, "values")?.value;
|
|
11230
|
+
if (inputValues === void 0) return { allow };
|
|
11231
|
+
if (inputValues === null || typeof inputValues !== "object" || Array.isArray(inputValues)) {
|
|
11232
|
+
throw new TypeError("Environment values must be an object.");
|
|
11233
|
+
}
|
|
11234
|
+
return {
|
|
11235
|
+
allow,
|
|
11236
|
+
values: Object.fromEntries(allow.map((name) => [name, readEnvValue(inputValues, name)]))
|
|
11237
|
+
};
|
|
11238
|
+
}
|
|
11239
|
+
function readEnvValue(values, name) {
|
|
11240
|
+
const descriptor = Object.getOwnPropertyDescriptor(values, name);
|
|
11241
|
+
if (descriptor === void 0) return void 0;
|
|
11242
|
+
if (!("value" in descriptor)) {
|
|
11243
|
+
throw new TypeError(`Environment value for ${JSON.stringify(name)} must not be an accessor.`);
|
|
11244
|
+
}
|
|
11245
|
+
if (descriptor.value !== void 0 && typeof descriptor.value !== "string") {
|
|
11246
|
+
throw new TypeError(
|
|
11247
|
+
`Environment value for ${JSON.stringify(name)} must be a string or undefined.`
|
|
11248
|
+
);
|
|
11249
|
+
}
|
|
11250
|
+
return descriptor.value;
|
|
11251
|
+
}
|
|
11252
|
+
function readEnvName(value, label) {
|
|
11253
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
11254
|
+
throw new TypeError(`${label} must be a non-empty string.`);
|
|
11255
|
+
}
|
|
11256
|
+
if (value.includes("\0") || value.includes("=")) {
|
|
11257
|
+
throw new TypeError(`${label} must not contain NUL or equals signs.`);
|
|
11258
|
+
}
|
|
11259
|
+
return value;
|
|
11260
|
+
}
|
|
11261
|
+
|
|
11262
|
+
// packages/safe-js/src/modules/fail.ts
|
|
11263
|
+
var HarnessFailure = class extends Error {
|
|
11264
|
+
constructor(message) {
|
|
11265
|
+
super(message);
|
|
11266
|
+
this.name = "HarnessFailure";
|
|
11267
|
+
}
|
|
11268
|
+
};
|
|
11269
|
+
function makeFailModule() {
|
|
11270
|
+
function fail(message) {
|
|
11271
|
+
throw new HarnessFailure(readNonEmptyString(message, "Harness failure message"));
|
|
11272
|
+
}
|
|
11273
|
+
return {
|
|
11274
|
+
default: fail
|
|
11275
|
+
};
|
|
11276
|
+
}
|
|
11277
|
+
function readNonEmptyString(value, label) {
|
|
11278
|
+
if (typeof value !== "string") {
|
|
11279
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
11280
|
+
}
|
|
11281
|
+
if (value.trim().length === 0) {
|
|
11282
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
11283
|
+
}
|
|
11284
|
+
return value;
|
|
11285
|
+
}
|
|
11286
|
+
|
|
11287
|
+
// packages/safe-js/src/modules/metric.ts
|
|
11288
|
+
function makeMetricModule(npmRunner) {
|
|
11289
|
+
return {
|
|
11290
|
+
async run(name) {
|
|
11291
|
+
const metricName = readNonEmptyString2(name, "Metric name");
|
|
11292
|
+
const scriptName = `metric:${metricName}`;
|
|
11293
|
+
const stdout = await npmRunner(scriptName);
|
|
11294
|
+
const score = parseMetricScore(stdout, scriptName);
|
|
11295
|
+
return score;
|
|
11296
|
+
}
|
|
11297
|
+
};
|
|
11298
|
+
}
|
|
11299
|
+
function parseMetricScore(stdout, scriptName) {
|
|
11300
|
+
if (typeof stdout !== "string") {
|
|
11301
|
+
throw new Error(`Metric runner for "${scriptName}" must resolve to a stdout string.`);
|
|
11302
|
+
}
|
|
11303
|
+
const scoreLine = stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).at(-1);
|
|
11304
|
+
if (scoreLine === void 0) {
|
|
11305
|
+
throw new Error(`Metric script "${scriptName}" must print a numeric score.`);
|
|
11306
|
+
}
|
|
11307
|
+
const score = Number(scoreLine);
|
|
11308
|
+
if (!Number.isFinite(score)) {
|
|
11309
|
+
throw new Error(`Metric script "${scriptName}" must print a numeric score.`);
|
|
11310
|
+
}
|
|
11311
|
+
return score;
|
|
11312
|
+
}
|
|
11313
|
+
function readNonEmptyString2(value, label) {
|
|
11314
|
+
if (typeof value !== "string") {
|
|
11315
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
11316
|
+
}
|
|
11317
|
+
const normalizedValue = value.trim();
|
|
11318
|
+
if (normalizedValue.length === 0) {
|
|
11319
|
+
throw new Error(`${label} must be a non-empty string.`);
|
|
11320
|
+
}
|
|
11321
|
+
return normalizedValue;
|
|
11322
|
+
}
|
|
11323
|
+
|
|
11177
11324
|
export {
|
|
11178
|
-
lint
|
|
11325
|
+
lint,
|
|
11326
|
+
EnvAccessError,
|
|
11327
|
+
makeEnvModule,
|
|
11328
|
+
parseEnvConfig,
|
|
11329
|
+
HarnessFailure,
|
|
11330
|
+
makeFailModule,
|
|
11331
|
+
makeMetricModule
|
|
11179
11332
|
};
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
McpError,
|
|
3
3
|
connectMcpTransport,
|
|
4
4
|
normalizeMcpOptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6H5VC5W5.js";
|
|
6
6
|
import {
|
|
7
7
|
declareHostOperation,
|
|
8
8
|
runResources
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5RLD4TVI.js";
|
|
10
10
|
import {
|
|
11
11
|
hostErrorData
|
|
12
12
|
} from "./chunk-A3LXCGMJ.js";
|