@veryfront/ext-content-mdx 0.1.1189 → 0.1.1191
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/esm/deno.d.ts +5 -0
- package/esm/deno.js +13 -5
- package/esm/src/errors/error-registry/agent.d.ts +2 -0
- package/esm/src/errors/error-registry/agent.d.ts.map +1 -1
- package/esm/src/errors/error-registry/agent.js +8 -0
- package/esm/src/errors/error-registry/module.d.ts +4 -0
- package/esm/src/errors/error-registry/module.d.ts.map +1 -1
- package/esm/src/errors/error-registry/module.js +16 -0
- package/esm/src/errors/error-registry/server.d.ts +6 -0
- package/esm/src/errors/error-registry/server.d.ts.map +1 -1
- package/esm/src/errors/error-registry/server.js +18 -0
- package/esm/src/errors/error-registry.d.ts +5 -0
- package/esm/src/errors/error-registry.d.ts.map +1 -1
- package/esm/src/errors/types.d.ts.map +1 -1
- package/esm/src/errors/types.js +5 -2
- package/esm/src/extensions/websocket/node-websocket-server-provider.d.ts +4 -4
- package/esm/src/extensions/websocket/node-websocket-server-provider.d.ts.map +1 -1
- package/esm/src/extensions/websocket/node-websocket-server-provider.js +4 -4
- package/esm/src/platform/adapters/file-snapshot-error.d.ts +7 -0
- package/esm/src/platform/adapters/file-snapshot-error.d.ts.map +1 -1
- package/esm/src/platform/adapters/file-snapshot-error.js +13 -0
- package/esm/src/platform/adapters/path-containment.d.ts +9 -0
- package/esm/src/platform/adapters/path-containment.d.ts.map +1 -0
- package/esm/src/platform/adapters/path-containment.js +13 -0
- package/esm/src/platform/adapters/runtime/shared/native-snapshot-identity.d.ts +13 -0
- package/esm/src/platform/adapters/runtime/shared/native-snapshot-identity.d.ts.map +1 -0
- package/esm/src/platform/adapters/runtime/shared/native-snapshot-identity.js +12 -0
- package/esm/src/platform/adapters/runtime/shared/node-filesystem-adapter.d.ts +7 -0
- package/esm/src/platform/adapters/runtime/shared/node-filesystem-adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/runtime/shared/node-filesystem-adapter.js +62 -18
- package/esm/src/platform/compat/error-introspection.d.ts +12 -1
- package/esm/src/platform/compat/error-introspection.d.ts.map +1 -1
- package/esm/src/platform/compat/error-introspection.js +40 -5
- package/esm/src/platform/compat/path/basic-operations.d.ts.map +1 -1
- package/esm/src/platform/compat/path/basic-operations.js +6 -2
- package/esm/src/platform/compat/path/portable.d.ts.map +1 -1
- package/esm/src/platform/compat/path/portable.js +98 -54
- package/esm/src/platform/compat/path/resolution.d.ts.map +1 -1
- package/esm/src/platform/compat/path/resolution.js +14 -5
- package/esm/src/platform/compat/primordials/array.d.ts +8 -0
- package/esm/src/platform/compat/primordials/array.d.ts.map +1 -0
- package/esm/src/platform/compat/primordials/array.js +33 -0
- package/esm/src/transforms/import-rewriter/url-builder.d.ts.map +1 -1
- package/esm/src/transforms/import-rewriter/url-builder.js +40 -14
- package/esm/src/utils/base64url.d.ts.map +1 -1
- package/esm/src/utils/base64url.js +10 -4
- package/esm/src/utils/bundle-manifest.d.ts +19 -1
- package/esm/src/utils/bundle-manifest.d.ts.map +1 -1
- package/esm/src/utils/bundle-manifest.js +124 -27
- package/esm/src/utils/constants/limits.d.ts +3 -1
- package/esm/src/utils/constants/limits.d.ts.map +1 -1
- package/esm/src/utils/constants/limits.js +3 -1
- package/esm/src/utils/hash-utils.d.ts.map +1 -1
- package/esm/src/utils/hash-utils.js +32 -6
- package/esm/src/utils/id.d.ts +16 -0
- package/esm/src/utils/id.d.ts.map +1 -0
- package/esm/src/utils/id.js +69 -0
- package/esm/src/utils/import-lockfile.d.ts +52 -1
- package/esm/src/utils/import-lockfile.d.ts.map +1 -1
- package/esm/src/utils/import-lockfile.js +1042 -58
- package/esm/src/utils/index.d.ts +1 -1
- package/esm/src/utils/index.d.ts.map +1 -1
- package/esm/src/utils/index.js +1 -1
- package/esm/src/utils/logger/logger.d.ts +1 -0
- package/esm/src/utils/logger/logger.d.ts.map +1 -1
- package/esm/src/utils/logger/logger.js +359 -78
- package/esm/src/utils/logger/redact.d.ts +4 -2
- package/esm/src/utils/logger/redact.d.ts.map +1 -1
- package/esm/src/utils/logger/redact.js +300 -112
- package/esm/src/utils/logger/serialization.d.ts +3 -0
- package/esm/src/utils/logger/serialization.d.ts.map +1 -0
- package/esm/src/utils/logger/serialization.js +81 -0
- package/esm/src/utils/memoize.d.ts +1 -1
- package/esm/src/utils/memoize.d.ts.map +1 -1
- package/esm/src/utils/memoize.js +16 -5
- package/esm/src/utils/path-utils.d.ts.map +1 -1
- package/esm/src/utils/path-utils.js +4 -2
- package/esm/src/utils/sleep.d.ts +8 -0
- package/esm/src/utils/sleep.d.ts.map +1 -1
- package/esm/src/utils/sleep.js +11 -2
- package/esm/src/utils/timer.d.ts +10 -0
- package/esm/src/utils/timer.d.ts.map +1 -0
- package/esm/src/utils/timer.js +19 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as dntShim from "../../../../../_dnt.shims.js";
|
|
1
2
|
import { createFileWatcher, createWatcherIterator, setupNodeFsWatcher } from "./shared-watcher.js";
|
|
2
3
|
import { makeNodeTempDir } from "./temp-dir.js";
|
|
3
4
|
import { isProxyWithoutHooks } from "../../../compat/error-introspection.js";
|
|
@@ -5,8 +6,11 @@ import { isCanonicalNotFoundError } from "../../../compat/not-found-error.js";
|
|
|
5
6
|
import { readBoundedFilePrefix, readFileWithinLimit, withFileHandle, } from "../../bounded-file-read.js";
|
|
6
7
|
import { markNativeFileSystemAdapter } from "../../native-file-system-provenance.js";
|
|
7
8
|
import { constants as nodeFsConstants } from "node:fs";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
9
|
+
import { resolve } from "../../../compat/path/index.js";
|
|
10
|
+
import { runtimeUsesWindowsPaths } from "../../../compat/path/portable.js";
|
|
11
|
+
import { FileSnapshotChangedError, FileSnapshotPathError } from "../../file-snapshot-error.js";
|
|
12
|
+
import { hasUsableNativeFileIdentity, } from "./native-snapshot-identity.js";
|
|
13
|
+
import { isPathContainedBy } from "../../path-containment.js";
|
|
10
14
|
const silentLogger = {
|
|
11
15
|
error: () => { },
|
|
12
16
|
debug: () => { },
|
|
@@ -56,10 +60,25 @@ const nodeFileSystemOperations = {
|
|
|
56
60
|
function hasOwn(value, property) {
|
|
57
61
|
return Object.prototype.hasOwnProperty.call(value, property);
|
|
58
62
|
}
|
|
59
|
-
function
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
function detectNodeCompatibleRuntime() {
|
|
64
|
+
const runtime = dntShim.dntGlobalThis;
|
|
65
|
+
const versions = runtime.process?.versions;
|
|
66
|
+
if (typeof versions?.deno === "string" || runtime.Deno !== undefined)
|
|
67
|
+
return "deno";
|
|
68
|
+
if (typeof versions?.bun === "string" || runtime.Bun !== undefined)
|
|
69
|
+
return "bun";
|
|
70
|
+
if (runtime.process?.release?.name === "node" &&
|
|
71
|
+
typeof versions?.node === "string") {
|
|
72
|
+
return "node";
|
|
73
|
+
}
|
|
74
|
+
return "unknown";
|
|
75
|
+
}
|
|
76
|
+
export function hasUsableWindowsSnapshotIdentity(runtime) {
|
|
77
|
+
// Node exposes bigint file identity and generation fields on Windows. Each
|
|
78
|
+
// snapshot still validates that the native identity is present and usable.
|
|
79
|
+
// Bun and Deno do not currently document an equivalent contract, so their
|
|
80
|
+
// Windows adapters must fail closed.
|
|
81
|
+
return runtime === "node";
|
|
63
82
|
}
|
|
64
83
|
function requirePositiveSafeInteger(value) {
|
|
65
84
|
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
@@ -75,6 +94,11 @@ function sameGeneration(left, right) {
|
|
|
75
94
|
left.mtimeNs === right.mtimeNs &&
|
|
76
95
|
left.ctimeNs === right.ctimeNs;
|
|
77
96
|
}
|
|
97
|
+
function requireUsableIdentity(stat, message) {
|
|
98
|
+
if (!hasUsableNativeFileIdentity(stat)) {
|
|
99
|
+
throw changed(message);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
78
102
|
function changed(message, cause) {
|
|
79
103
|
const error = new FileSnapshotChangedError(message);
|
|
80
104
|
if (cause !== undefined) {
|
|
@@ -108,24 +132,36 @@ function throwSnapshotChangeForPathRace(message, cause) {
|
|
|
108
132
|
}
|
|
109
133
|
throwSnapshotChangeForMissingPath(message, cause);
|
|
110
134
|
}
|
|
111
|
-
async function readNodeFileSnapshotWithinLimit(operations, noFollow, path, containmentRoot, byteLimit) {
|
|
135
|
+
export async function readNodeFileSnapshotWithinLimit(operations, platform, noFollow, path, containmentRoot, byteLimit) {
|
|
112
136
|
requirePositiveSafeInteger(byteLimit);
|
|
137
|
+
let openFlags;
|
|
138
|
+
if (platform === "windows") {
|
|
139
|
+
openFlags = "r";
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
if (typeof noFollow !== "number" || noFollow === 0) {
|
|
143
|
+
throw new TypeError("This runtime cannot guarantee no-follow snapshot opens");
|
|
144
|
+
}
|
|
145
|
+
openFlags = nodeFsConstants.O_RDONLY | noFollow;
|
|
146
|
+
}
|
|
113
147
|
const lexicalRoot = resolve(containmentRoot);
|
|
114
148
|
const candidate = resolve(path);
|
|
115
|
-
if (!isContainedPath(candidate, lexicalRoot)) {
|
|
116
|
-
throw new TypeError("Snapshot path must be contained by the requested root");
|
|
117
|
-
}
|
|
118
149
|
const canonicalRoot = await operations.realpath(lexicalRoot);
|
|
150
|
+
if (!isPathContainedBy(candidate, lexicalRoot) &&
|
|
151
|
+
!isPathContainedBy(candidate, canonicalRoot)) {
|
|
152
|
+
throw new FileSnapshotPathError("Snapshot path must be contained by the requested root");
|
|
153
|
+
}
|
|
119
154
|
const pathnameBefore = await operations.lstat(candidate);
|
|
120
155
|
if (pathnameBefore.isSymbolicLink()) {
|
|
121
|
-
throw new
|
|
156
|
+
throw new FileSnapshotPathError("Snapshot path must not be a symbolic link");
|
|
122
157
|
}
|
|
123
158
|
if (!pathnameBefore.isFile()) {
|
|
124
|
-
throw new
|
|
159
|
+
throw new FileSnapshotPathError("Snapshot path must identify a regular file");
|
|
125
160
|
}
|
|
161
|
+
requireUsableIdentity(pathnameBefore, "Stable native file identity is unavailable for the snapshot path");
|
|
126
162
|
return await withFileHandle(async () => {
|
|
127
163
|
try {
|
|
128
|
-
return await operations.open(candidate,
|
|
164
|
+
return await operations.open(candidate, openFlags);
|
|
129
165
|
}
|
|
130
166
|
catch (cause) {
|
|
131
167
|
throwSnapshotChangeForPathRace("File identity became uncertain while opening the snapshot", cause);
|
|
@@ -138,6 +174,7 @@ async function readNodeFileSnapshotWithinLimit(operations, noFollow, path, conta
|
|
|
138
174
|
catch (cause) {
|
|
139
175
|
throwSnapshotChangeForMissingPath("Opened file identity could not be verified", cause);
|
|
140
176
|
}
|
|
177
|
+
requireUsableIdentity(handleBefore, "Stable native file identity is unavailable for the opened snapshot");
|
|
141
178
|
if (!handleBefore.isFile() || !sameGeneration(pathnameBefore, handleBefore)) {
|
|
142
179
|
throw changed("File identity changed while opening the snapshot");
|
|
143
180
|
}
|
|
@@ -157,8 +194,9 @@ async function readNodeFileSnapshotWithinLimit(operations, noFollow, path, conta
|
|
|
157
194
|
!sameGeneration(handleBefore, pathnameOpened)) {
|
|
158
195
|
throw changed("File identity changed while opening the snapshot");
|
|
159
196
|
}
|
|
160
|
-
|
|
161
|
-
|
|
197
|
+
requireUsableIdentity(pathnameOpened, "Stable native file identity is unavailable while verifying the snapshot");
|
|
198
|
+
if (!isPathContainedBy(canonicalTarget, canonicalRoot)) {
|
|
199
|
+
throw new FileSnapshotPathError("Snapshot target must be contained by the canonical root");
|
|
162
200
|
}
|
|
163
201
|
if (handleBefore.size < 0n) {
|
|
164
202
|
throw changed("File size became uncertain while opening the snapshot");
|
|
@@ -200,12 +238,14 @@ async function readNodeFileSnapshotWithinLimit(operations, noFollow, path, conta
|
|
|
200
238
|
catch (cause) {
|
|
201
239
|
throwSnapshotChangeForPathRace("File identity became uncertain after reading the snapshot", cause);
|
|
202
240
|
}
|
|
241
|
+
requireUsableIdentity(handleAfter, "Stable native file identity is unavailable after reading the snapshot");
|
|
242
|
+
requireUsableIdentity(pathnameAfter, "Stable native file identity is unavailable after reading the snapshot path");
|
|
203
243
|
if (!pathnameAfter.isFile() ||
|
|
204
244
|
pathnameAfter.isSymbolicLink() ||
|
|
205
245
|
!sameGeneration(handleBefore, handleAfter) ||
|
|
206
246
|
!sameGeneration(handleBefore, pathnameAfter) ||
|
|
207
247
|
canonicalTargetAfter !== canonicalTarget ||
|
|
208
|
-
!
|
|
248
|
+
!isPathContainedBy(canonicalTargetAfter, canonicalRoot)) {
|
|
209
249
|
throw changed("File snapshot changed during the read");
|
|
210
250
|
}
|
|
211
251
|
return bytes;
|
|
@@ -227,9 +267,13 @@ export class NodeCompatibleFileSystemAdapter {
|
|
|
227
267
|
...options.operations,
|
|
228
268
|
};
|
|
229
269
|
const noFollow = hasOwn(options, "noFollow") ? options.noFollow : nodeFsConstants.O_NOFOLLOW;
|
|
230
|
-
|
|
270
|
+
const platform = options.platform ?? (runtimeUsesWindowsPaths() ? "windows" : "posix");
|
|
271
|
+
const canOpenExactSnapshot = platform === "windows"
|
|
272
|
+
? hasUsableWindowsSnapshotIdentity(detectNodeCompatibleRuntime())
|
|
273
|
+
: typeof noFollow === "number" && noFollow !== 0;
|
|
274
|
+
if (canOpenExactSnapshot) {
|
|
231
275
|
Object.defineProperty(this, "readFileSnapshotWithinLimit", {
|
|
232
|
-
value: (path, containmentRoot, byteLimit) => readNodeFileSnapshotWithinLimit(operations, noFollow, path, containmentRoot, byteLimit),
|
|
276
|
+
value: (path, containmentRoot, byteLimit) => readNodeFileSnapshotWithinLimit(operations, platform, noFollow, path, containmentRoot, byteLimit),
|
|
233
277
|
enumerable: true,
|
|
234
278
|
});
|
|
235
279
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this runtime can distinguish Proxy values without evaluating a trap.
|
|
3
|
+
* Callers that need a fail-closed guarantee must not treat a `false` result
|
|
4
|
+
* from {@link isProxyWithoutHooks} as proof when this capability is absent.
|
|
5
|
+
*/
|
|
6
|
+
export declare const canIdentifyProxyWithoutHooks: boolean;
|
|
1
7
|
/** True when own stack descriptors can be inspected without formatting them. */
|
|
2
8
|
export declare const canInspectErrorStackDescriptorWithoutHooks: boolean;
|
|
3
9
|
/**
|
|
@@ -22,7 +28,12 @@ export declare function isNativeErrorWithoutHooks(value: unknown): value is Erro
|
|
|
22
28
|
* prototype name or constructor name; unreadable/exotic shapes fail closed.
|
|
23
29
|
*/
|
|
24
30
|
export declare function readNativeErrorNameWithoutHooks(error: Error): string;
|
|
25
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Identify a Proxy without evaluating any trap on the proxied value.
|
|
33
|
+
*
|
|
34
|
+
* Returns `false` without inspecting `value` when
|
|
35
|
+
* {@link canIdentifyProxyWithoutHooks} is false.
|
|
36
|
+
*/
|
|
26
37
|
export declare function isProxyWithoutHooks(value: unknown): boolean;
|
|
27
38
|
/** Identify a genuine Uint8Array without evaluating project-owned hooks. */
|
|
28
39
|
export declare function isUint8ArrayWithoutHooks(value: unknown): value is Uint8Array;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-introspection.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/error-introspection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error-introspection.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/error-introspection.ts"],"names":[],"mappings":"AA0DA;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,SAAkC,CAAC;AA8F5E,gFAAgF;AAChF,eAAO,MAAM,0CAA0C,SAA0C,CAAC;AAgClG;;;;;;;;;;GAUG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAuBjF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAExE;AA6BD;;;;GAIG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAkBpE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED,4EAA4E;AAC5E,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAE5E;AAED,gFAAgF;AAChF,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAE3B;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAgBnD"}
|
|
@@ -16,15 +16,45 @@ const apply = Reflect.apply;
|
|
|
16
16
|
const NativeError = Error;
|
|
17
17
|
const NativeAsyncFunctionPrototype = getPrototypeOf(async function () { });
|
|
18
18
|
const toStringTagSymbol = Symbol.toStringTag;
|
|
19
|
+
function hasOwn(object, key) {
|
|
20
|
+
return apply(objectHasOwnProperty, object, [key]);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Capture the portable Error brand primitive during trusted framework
|
|
24
|
+
* bootstrap, before tenant code can replace mutable globals. Edge runtimes do
|
|
25
|
+
* not expose an immutable host-module equivalent, so this capture boundary is
|
|
26
|
+
* the authority for later no-hook Error checks.
|
|
27
|
+
*/
|
|
28
|
+
function captureErrorIsError() {
|
|
29
|
+
const descriptor = getOwnPropertyDescriptor(NativeError, "isError");
|
|
30
|
+
return descriptor && hasOwn(descriptor, "value") &&
|
|
31
|
+
typeof descriptor.value === "function"
|
|
32
|
+
? descriptor.value
|
|
33
|
+
: undefined;
|
|
34
|
+
}
|
|
35
|
+
const capturedErrorIsError = captureErrorIsError();
|
|
19
36
|
const unavailableBrandCheck = (_value) => false;
|
|
37
|
+
function portableErrorBrandCheck(value) {
|
|
38
|
+
if (!capturedErrorIsError)
|
|
39
|
+
return false;
|
|
40
|
+
try {
|
|
41
|
+
return apply(capturedErrorIsError, NativeError, [value]) === true;
|
|
42
|
+
}
|
|
43
|
+
catch (_) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
20
47
|
const nativeAsyncFunctionBrandCheck = nativeBrandChecks?.isAsyncFunction ?? unavailableBrandCheck;
|
|
21
|
-
const nativeErrorBrandCheck = nativeBrandChecks?.isNativeError ??
|
|
48
|
+
const nativeErrorBrandCheck = nativeBrandChecks?.isNativeError ?? portableErrorBrandCheck;
|
|
22
49
|
const nativePromiseBrandCheck = nativeBrandChecks?.isPromise ?? unavailableBrandCheck;
|
|
23
50
|
const nativeProxyBrandCheck = nativeBrandChecks?.isProxy ?? unavailableBrandCheck;
|
|
24
51
|
const nativeUint8ArrayBrandCheck = nativeBrandChecks?.isUint8Array ?? unavailableBrandCheck;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Whether this runtime can distinguish Proxy values without evaluating a trap.
|
|
54
|
+
* Callers that need a fail-closed guarantee must not treat a `false` result
|
|
55
|
+
* from {@link isProxyWithoutHooks} as proof when this capability is absent.
|
|
56
|
+
*/
|
|
57
|
+
export const canIdentifyProxyWithoutHooks = nativeBrandChecks !== undefined;
|
|
28
58
|
function createDataDescriptor(value) {
|
|
29
59
|
const descriptor = createObject(null);
|
|
30
60
|
descriptor.configurable = true;
|
|
@@ -219,7 +249,12 @@ export function readNativeErrorNameWithoutHooks(error) {
|
|
|
219
249
|
return "Error";
|
|
220
250
|
}
|
|
221
251
|
}
|
|
222
|
-
/**
|
|
252
|
+
/**
|
|
253
|
+
* Identify a Proxy without evaluating any trap on the proxied value.
|
|
254
|
+
*
|
|
255
|
+
* Returns `false` without inspecting `value` when
|
|
256
|
+
* {@link canIdentifyProxyWithoutHooks} is false.
|
|
257
|
+
*/
|
|
223
258
|
export function isProxyWithoutHooks(value) {
|
|
224
259
|
return nativeProxyBrandCheck(value);
|
|
225
260
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic-operations.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/basic-operations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"basic-operations.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/basic-operations.ts"],"names":[],"mappings":"AAqBA,yEAAyE;AACzE,wBAAgB,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAU/C;AAED,wCAAwC;AACxC,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,oCAAoC;AACpC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5C"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { hasWindowsLikePath, portableBasename, portableDirname, portableExtname, portableJoin, removeTrailingSeparatorsExceptRoot, runtimeUsesWindowsPaths, toPortableSeparators, } from "./portable.js";
|
|
2
2
|
import { getNativePathImplementation } from "./runtime.js";
|
|
3
|
+
const ArrayPrototypeEvery = Array.prototype.every;
|
|
4
|
+
const ArrayPrototypeSome = Array.prototype.some;
|
|
5
|
+
const ReflectApply = Reflect.apply;
|
|
3
6
|
function usesWindowsFlavor(paths) {
|
|
4
|
-
return runtimeUsesWindowsPaths() ||
|
|
7
|
+
return runtimeUsesWindowsPaths() ||
|
|
8
|
+
ReflectApply(ArrayPrototypeSome, paths, [hasWindowsLikePath]);
|
|
5
9
|
}
|
|
6
10
|
/** Join and normalize path segments using their detected path flavor. */
|
|
7
11
|
export function join(...paths) {
|
|
8
|
-
if (paths
|
|
12
|
+
if (ReflectApply(ArrayPrototypeEvery, paths, [(path) => path.length === 0]))
|
|
9
13
|
return "/";
|
|
10
14
|
const windows = usesWindowsFlavor(paths);
|
|
11
15
|
const pathApi = getNativePathImplementation(windows);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/portable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"portable.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/portable.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAoD7C,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AA2FD,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,GACf,MAAM,CAUR;AAOD,wBAAgB,uBAAuB,IAAI,OAAO,CASjD;AAyBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAkBxE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAI/E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAqBtE;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,EAAE,OAAO,GACf,MAAM,CAuCR;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAKtE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAE1E;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE,OAAO,GACf,MAAM,CAkCR;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,GACf,MAAM,CAiCR;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,CAiCxE;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,GACf,MAAM,CAeR"}
|
|
@@ -1,15 +1,44 @@
|
|
|
1
1
|
import * as dntShim from "../../../../_dnt.shims.js";
|
|
2
|
+
import { primordialArrayAt as arrayAt, primordialArrayFilter as arrayFilter, primordialArrayJoin as arrayJoin, primordialArrayPop as arrayPop, primordialArrayPush as arrayPush, } from "../primordials/array.js";
|
|
3
|
+
const apply = Reflect.apply;
|
|
4
|
+
const arraySlice = Array.prototype.slice;
|
|
5
|
+
const regExpExec = RegExp.prototype.exec;
|
|
6
|
+
const stringEndsWith = String.prototype.endsWith;
|
|
7
|
+
const stringIncludes = String.prototype.includes;
|
|
8
|
+
const stringLastIndexOf = String.prototype.lastIndexOf;
|
|
9
|
+
const stringReplaceAll = String.prototype.replaceAll;
|
|
10
|
+
const stringSlice = String.prototype.slice;
|
|
11
|
+
const stringSplit = String.prototype.split;
|
|
12
|
+
const stringStartsWith = String.prototype.startsWith;
|
|
13
|
+
const stringToLowerCase = String.prototype.toLowerCase;
|
|
14
|
+
function includes(value, search) {
|
|
15
|
+
return apply(stringIncludes, value, [search]);
|
|
16
|
+
}
|
|
17
|
+
function startsWith(value, search) {
|
|
18
|
+
return apply(stringStartsWith, value, [search]);
|
|
19
|
+
}
|
|
20
|
+
function endsWith(value, search) {
|
|
21
|
+
return apply(stringEndsWith, value, [search]);
|
|
22
|
+
}
|
|
23
|
+
function slice(value, start, end) {
|
|
24
|
+
return apply(stringSlice, value, end === undefined ? [start] : [start, end]);
|
|
25
|
+
}
|
|
26
|
+
function lastIndexOf(value, search) {
|
|
27
|
+
return apply(stringLastIndexOf, value, [search]);
|
|
28
|
+
}
|
|
29
|
+
function matches(pattern, value) {
|
|
30
|
+
return apply(regExpExec, pattern, [value]);
|
|
31
|
+
}
|
|
2
32
|
export function hasWindowsLikePath(path) {
|
|
3
|
-
return
|
|
4
|
-
/^[A-Za-z]:/.test(path);
|
|
33
|
+
return includes(path, "\\") || matches(/^[A-Za-z]:/, path) !== null;
|
|
5
34
|
}
|
|
6
35
|
export function toPortableSeparators(path) {
|
|
7
|
-
return path
|
|
36
|
+
return apply(stringReplaceAll, path, ["\\", "/"]);
|
|
8
37
|
}
|
|
9
38
|
function analyzeRoot(path, windows) {
|
|
10
39
|
const portable = toPortableSeparators(path);
|
|
11
40
|
if (windows) {
|
|
12
|
-
const unc =
|
|
41
|
+
const unc = matches(/^\/\/([^/]+)\/+([^/]+)(\/+(.*))?$/, portable);
|
|
13
42
|
if (unc?.[1] && unc[2]) {
|
|
14
43
|
const device = `//${unc[1]}/${unc[2]}`;
|
|
15
44
|
return {
|
|
@@ -19,7 +48,7 @@ function analyzeRoot(path, windows) {
|
|
|
19
48
|
root: unc[3] === undefined ? device : `${device}/`,
|
|
20
49
|
};
|
|
21
50
|
}
|
|
22
|
-
const drive =
|
|
51
|
+
const drive = matches(/^([A-Za-z]:)(\/+)?(.*)$/, portable);
|
|
23
52
|
if (drive?.[1] !== undefined) {
|
|
24
53
|
const absolute = drive[2] !== undefined;
|
|
25
54
|
return {
|
|
@@ -30,11 +59,14 @@ function analyzeRoot(path, windows) {
|
|
|
30
59
|
};
|
|
31
60
|
}
|
|
32
61
|
}
|
|
33
|
-
if (
|
|
62
|
+
if (startsWith(portable, "/")) {
|
|
63
|
+
let restStart = 0;
|
|
64
|
+
while (portable[restStart] === "/")
|
|
65
|
+
restStart++;
|
|
34
66
|
return {
|
|
35
67
|
absolute: true,
|
|
36
68
|
device: "",
|
|
37
|
-
rest: portable
|
|
69
|
+
rest: slice(portable, restStart),
|
|
38
70
|
root: "/",
|
|
39
71
|
};
|
|
40
72
|
}
|
|
@@ -51,25 +83,30 @@ function appendRoot(root, tail) {
|
|
|
51
83
|
if (!root.absolute)
|
|
52
84
|
return `${root.root}${tail || "."}`;
|
|
53
85
|
if (!tail) {
|
|
54
|
-
return root.device
|
|
86
|
+
return startsWith(root.device, "//") ? `${root.device}/` : root.root;
|
|
55
87
|
}
|
|
56
|
-
return root.root
|
|
88
|
+
return endsWith(root.root, "/") ? `${root.root}${tail}` : `${root.root}/${tail}`;
|
|
57
89
|
}
|
|
58
90
|
function normalizeTail(rest, absolute) {
|
|
59
91
|
const normalized = [];
|
|
60
|
-
|
|
92
|
+
const segments = apply(stringSplit, rest, ["/"]);
|
|
93
|
+
// Path normalization is reached by shared-runtime coordination after tenant
|
|
94
|
+
// code has loaded. Avoid the live Array iterator so post-import prototype
|
|
95
|
+
// mutation cannot turn canonical lockfile lookup into a process-wide outage.
|
|
96
|
+
for (let index = 0; index < segments.length; index++) {
|
|
97
|
+
const segment = segments[index];
|
|
61
98
|
if (segment === "" || segment === ".")
|
|
62
99
|
continue;
|
|
63
100
|
if (segment !== "..") {
|
|
64
|
-
normalized
|
|
101
|
+
arrayPush(normalized, segment);
|
|
65
102
|
continue;
|
|
66
103
|
}
|
|
67
|
-
const previous = normalized
|
|
104
|
+
const previous = arrayAt(normalized, -1);
|
|
68
105
|
if (previous !== undefined && previous !== "..") {
|
|
69
|
-
normalized
|
|
106
|
+
arrayPop(normalized);
|
|
70
107
|
}
|
|
71
108
|
else if (!absolute) {
|
|
72
|
-
normalized
|
|
109
|
+
arrayPush(normalized, "..");
|
|
73
110
|
}
|
|
74
111
|
}
|
|
75
112
|
return normalized;
|
|
@@ -80,15 +117,15 @@ function canonicalPath(path, windows) {
|
|
|
80
117
|
export function removeTrailingSeparatorsExceptRoot(path, windows) {
|
|
81
118
|
const root = analyzeRoot(path, windows);
|
|
82
119
|
let canonical = canonicalPath(path, windows);
|
|
83
|
-
while (
|
|
120
|
+
while (endsWith(canonical, "/") &&
|
|
84
121
|
canonical.length > root.root.length) {
|
|
85
|
-
canonical =
|
|
122
|
+
canonical = slice(canonical, 0, -1);
|
|
86
123
|
}
|
|
87
124
|
return canonical;
|
|
88
125
|
}
|
|
89
126
|
function rootKey(root, windows) {
|
|
90
127
|
const value = root.device || root.root;
|
|
91
|
-
return windows ? value
|
|
128
|
+
return windows ? apply(stringToLowerCase, value, []) : value;
|
|
92
129
|
}
|
|
93
130
|
export function runtimeUsesWindowsPaths() {
|
|
94
131
|
const runtime = dntShim.dntGlobalThis;
|
|
@@ -121,44 +158,44 @@ export function portableNormalize(path, windows) {
|
|
|
121
158
|
if (path === "")
|
|
122
159
|
return ".";
|
|
123
160
|
const root = analyzeRoot(path, windows);
|
|
124
|
-
const tail = normalizeTail(root.rest, root.absolute)
|
|
161
|
+
const tail = arrayJoin(normalizeTail(root.rest, root.absolute), "/");
|
|
125
162
|
let result = appendRoot(root, tail);
|
|
126
|
-
const hadTrailingSeparator = /[\\/]
|
|
163
|
+
const hadTrailingSeparator = matches(/[\\/]$/, path) !== null;
|
|
127
164
|
if (hadTrailingSeparator && result === ".")
|
|
128
165
|
return "./";
|
|
129
166
|
if (hadTrailingSeparator &&
|
|
130
167
|
result !== root.root &&
|
|
131
|
-
!
|
|
168
|
+
!endsWith(result, "/")) {
|
|
132
169
|
result += "/";
|
|
133
170
|
}
|
|
134
171
|
return result;
|
|
135
172
|
}
|
|
136
173
|
export function portableJoin(paths, windows) {
|
|
137
|
-
const nonempty = paths
|
|
174
|
+
const nonempty = arrayFilter(paths, (path) => path.length > 0);
|
|
138
175
|
if (nonempty.length === 0)
|
|
139
176
|
return "/";
|
|
140
|
-
return portableNormalize(nonempty
|
|
177
|
+
return portableNormalize(arrayJoin(nonempty, "/"), windows);
|
|
141
178
|
}
|
|
142
179
|
export function portableDirname(path, windows) {
|
|
143
180
|
if (path.length === 0)
|
|
144
181
|
return ".";
|
|
145
182
|
const root = analyzeRoot(path, windows);
|
|
146
183
|
let canonical = canonicalPath(path, windows);
|
|
147
|
-
while (
|
|
184
|
+
while (endsWith(canonical, "/") &&
|
|
148
185
|
canonical.length > root.root.length) {
|
|
149
|
-
canonical =
|
|
186
|
+
canonical = slice(canonical, 0, -1);
|
|
150
187
|
}
|
|
151
188
|
if (canonical === root.root || canonical === root.device) {
|
|
152
189
|
return root.root || root.device || ".";
|
|
153
190
|
}
|
|
154
|
-
const lastSeparator =
|
|
191
|
+
const lastSeparator = lastIndexOf(canonical, "/");
|
|
155
192
|
if (lastSeparator === -1)
|
|
156
193
|
return root.device || ".";
|
|
157
194
|
if (lastSeparator < root.root.length)
|
|
158
195
|
return root.root || "/";
|
|
159
196
|
if (lastSeparator === 0)
|
|
160
197
|
return "/";
|
|
161
|
-
return
|
|
198
|
+
return slice(canonical, 0, lastSeparator);
|
|
162
199
|
}
|
|
163
200
|
export function portableBasename(path, ext, windows) {
|
|
164
201
|
if (path.length === 0)
|
|
@@ -168,44 +205,45 @@ export function portableBasename(path, ext, windows) {
|
|
|
168
205
|
const originalPath = canonical;
|
|
169
206
|
if (ext !== undefined && ext !== "" && ext === originalPath)
|
|
170
207
|
return "";
|
|
171
|
-
while (
|
|
208
|
+
while (endsWith(canonical, "/") &&
|
|
172
209
|
canonical.length > root.root.length) {
|
|
173
|
-
canonical =
|
|
210
|
+
canonical = slice(canonical, 0, -1);
|
|
174
211
|
}
|
|
175
212
|
if (windows &&
|
|
176
|
-
root.device
|
|
213
|
+
startsWith(root.device, "//") &&
|
|
177
214
|
root.rest === "") {
|
|
178
|
-
return root.device
|
|
215
|
+
return slice(root.device, lastIndexOf(root.device, "/") + 1);
|
|
179
216
|
}
|
|
180
217
|
if (canonical === root.root || canonical === root.device)
|
|
181
218
|
return "";
|
|
182
|
-
const lastSeparator =
|
|
183
|
-
let base =
|
|
219
|
+
const lastSeparator = lastIndexOf(canonical, "/");
|
|
220
|
+
let base = slice(canonical, lastSeparator + 1);
|
|
184
221
|
if (!root.absolute &&
|
|
185
222
|
root.device &&
|
|
186
223
|
lastSeparator === -1 &&
|
|
187
|
-
|
|
188
|
-
base =
|
|
224
|
+
startsWith(base, root.device)) {
|
|
225
|
+
base = slice(base, root.device.length);
|
|
189
226
|
}
|
|
190
|
-
if (ext !== undefined && ext !== "" &&
|
|
227
|
+
if (ext !== undefined && ext !== "" && endsWith(base, ext)) {
|
|
191
228
|
if (ext.length < base.length)
|
|
192
|
-
return
|
|
229
|
+
return slice(base, 0, -ext.length);
|
|
193
230
|
}
|
|
194
231
|
return base;
|
|
195
232
|
}
|
|
196
233
|
export function portableExtname(path, windows) {
|
|
197
234
|
const base = portableBasename(path, undefined, windows);
|
|
198
|
-
const lastDot =
|
|
235
|
+
const lastDot = lastIndexOf(base, ".");
|
|
199
236
|
if (lastDot <= 0 || base === "." || base === "..")
|
|
200
237
|
return "";
|
|
201
|
-
return
|
|
238
|
+
return slice(base, lastDot);
|
|
202
239
|
}
|
|
203
240
|
export function portableIsAbsolute(path, windows) {
|
|
204
241
|
return analyzeRoot(path, windows).absolute;
|
|
205
242
|
}
|
|
206
243
|
export function portableResolve(paths, windows) {
|
|
207
244
|
let resolved = runtimeCwd();
|
|
208
|
-
for (
|
|
245
|
+
for (let index = 0; index < paths.length; index++) {
|
|
246
|
+
const rawPath = paths[index];
|
|
209
247
|
if (rawPath.length === 0)
|
|
210
248
|
continue;
|
|
211
249
|
const path = toPortableSeparators(rawPath);
|
|
@@ -228,10 +266,10 @@ export function portableResolve(paths, windows) {
|
|
|
228
266
|
}
|
|
229
267
|
const normalized = portableNormalize(resolved, windows);
|
|
230
268
|
const root = analyzeRoot(normalized, windows);
|
|
231
|
-
if (
|
|
269
|
+
if (endsWith(normalized, "/") &&
|
|
232
270
|
normalized !== root.root &&
|
|
233
271
|
normalized !== `${root.device}/`) {
|
|
234
|
-
return
|
|
272
|
+
return slice(normalized, 0, -1);
|
|
235
273
|
}
|
|
236
274
|
return normalized;
|
|
237
275
|
}
|
|
@@ -249,34 +287,40 @@ export function portableRelative(from, to, windows) {
|
|
|
249
287
|
while (common < fromParts.length && common < toParts.length) {
|
|
250
288
|
const fromPart = fromParts[common];
|
|
251
289
|
const toPart = toParts[common];
|
|
252
|
-
const equal = windows
|
|
290
|
+
const equal = windows
|
|
291
|
+
? apply(stringToLowerCase, fromPart, []) === apply(stringToLowerCase, toPart, [])
|
|
292
|
+
: fromPart === toPart;
|
|
253
293
|
if (!equal)
|
|
254
294
|
break;
|
|
255
295
|
common++;
|
|
256
296
|
}
|
|
257
|
-
const result = [
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
297
|
+
const result = [];
|
|
298
|
+
for (let index = common; index < fromParts.length; index++) {
|
|
299
|
+
arrayPush(result, "..");
|
|
300
|
+
}
|
|
301
|
+
const remainingToParts = apply(arraySlice, toParts, [common]);
|
|
302
|
+
for (let index = 0; index < remainingToParts.length; index++) {
|
|
303
|
+
arrayPush(result, remainingToParts[index]);
|
|
304
|
+
}
|
|
305
|
+
return arrayJoin(result, "/") || ".";
|
|
262
306
|
}
|
|
263
307
|
export function portableParse(path, windows) {
|
|
264
308
|
const root = analyzeRoot(path, windows);
|
|
265
309
|
let canonical = canonicalPath(path, windows);
|
|
266
|
-
while (
|
|
310
|
+
while (endsWith(canonical, "/") &&
|
|
267
311
|
canonical.length > root.root.length) {
|
|
268
|
-
canonical =
|
|
312
|
+
canonical = slice(canonical, 0, -1);
|
|
269
313
|
}
|
|
270
|
-
const base = windows && root.device
|
|
314
|
+
const base = windows && startsWith(root.device, "//") && root.rest === ""
|
|
271
315
|
? ""
|
|
272
316
|
: portableBasename(canonical, undefined, windows);
|
|
273
317
|
const ext = portableExtname(base, windows);
|
|
274
|
-
const name =
|
|
318
|
+
const name = slice(base, 0, base.length - ext.length);
|
|
275
319
|
let dir = "";
|
|
276
320
|
if (base === "") {
|
|
277
321
|
dir = root.root;
|
|
278
322
|
}
|
|
279
|
-
else if (
|
|
323
|
+
else if (includes(canonical, "/") ||
|
|
280
324
|
(windows && root.device !== "")) {
|
|
281
325
|
dir = portableDirname(canonical, windows);
|
|
282
326
|
}
|
|
@@ -292,7 +336,7 @@ export function portableFormat(pathObject, windows) {
|
|
|
292
336
|
const root = toPortableSeparators(pathObject.root ?? "");
|
|
293
337
|
const dir = toPortableSeparators(pathObject.dir ?? "");
|
|
294
338
|
const rawExt = pathObject.ext ?? "";
|
|
295
|
-
const ext = rawExt && !
|
|
339
|
+
const ext = rawExt && !startsWith(rawExt, ".") ? `.${rawExt}` : rawExt;
|
|
296
340
|
const base = pathObject.base ||
|
|
297
341
|
`${pathObject.name ?? ""}${ext}`;
|
|
298
342
|
const directory = dir || root;
|
|
@@ -300,7 +344,7 @@ export function portableFormat(pathObject, windows) {
|
|
|
300
344
|
return base;
|
|
301
345
|
if (!base)
|
|
302
346
|
return directory;
|
|
303
|
-
if (
|
|
347
|
+
if (endsWith(directory, "/") || (windows && matches(/^[A-Za-z]:$/, directory) !== null)) {
|
|
304
348
|
return `${directory}${base}`;
|
|
305
349
|
}
|
|
306
350
|
return `${directory}/${base}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/resolution.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolution.d.ts","sourceRoot":"","sources":["../../../../../src/src/platform/compat/path/resolution.ts"],"names":[],"mappings":"AAsBA,6DAA6D;AAC7D,wBAAgB,OAAO,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAMlD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMhD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW9C"}
|