fix(javascript): require complete receiver ownership proofs

This commit is contained in:
morluto
2026-10-24 07:42:13 +08:00
parent cc4f805541
commit 2496256cb7
5 changed files with 383 additions and 311 deletions
@@ -90,6 +90,18 @@ const joinAmbientProjection = (
? undefined
: left.map((key, index) => (key === right[index] ? key : null));
type AmbientIdentityUnknownReason =
| "unresolved-value"
| "widened-projection"
| "unresolved-call"
| "mixed-identities";
interface AmbientResolution {
readonly paths: readonly AmbientPath[];
readonly ownership: "local" | "ambient" | "unknown";
readonly unknownReasons: readonly AmbientIdentityUnknownReason[];
}
interface AmbientReferenceFacts {
readonly stores: WeakMap<
t.Node,
@@ -109,7 +121,7 @@ export const createAmbientPathResolver = (
possibleWrites: boolean,
facts?: AmbientReferenceFacts,
) => {
const cached = new WeakMap<t.Node, readonly AmbientPath[]>();
const cached = new WeakMap<t.Node, AmbientResolution>();
const returnedReferences = createSemanticReturnedReferences(state);
return (
node: t.Node,
@@ -117,10 +129,12 @@ export const createAmbientPathResolver = (
escapedContents = false,
projection: AmbientProjection = [],
localIdentity?: (node: t.Node, path: AmbientProjection) => void,
): readonly AmbientPath[] => {
): AmbientResolution => {
const prior = possibleWrites ? undefined : cached.get(node);
if (prior !== undefined) return prior;
const result = new Map<string, AmbientPath>();
let hasLocalIdentity = false;
const unknownReasons = new Set<AmbientIdentityUnknownReason>();
// The caller's write site selects initializers for the written target.
// Reads reached through an initializer occur at their own position.
const pending: {
@@ -159,81 +173,61 @@ export const createAmbientPathResolver = (
while (pending.length > 0) {
const current = pending.pop();
if (current === undefined) break;
const { root, members } = electronMemberPath(current.node);
let suffix: AmbientProjection =
current.suffix === undefined
? undefined
: [...members, ...current.suffix];
if (expanded.has(root)) {
const previous = expanded.get(root);
if (previous === undefined) continue;
if (suffix !== undefined && previous.length === suffix.length) {
const joined: AmbientPath = previous.map((key, index) =>
key === suffix?.[index] ? key : null,
);
if (joined.every((key, index) => key === previous[index])) continue;
suffix = joined;
} else suffix = undefined;
if (!possibleWrites) {
cached.set(node, []);
return [];
}
}
expanded.set(root, suffix);
// A widened projection is a possible write, never proof of an intrinsic.
if (suffix === undefined && !possibleWrites) continue;
const continueWith = (node: t.Node, path: AmbientProjection = suffix) =>
pending.push({
node,
suffix: path,
...(current.readsAtSelf && { readsAtSelf: true }),
});
const continueReturned = (callee: t.Node, path: AmbientProjection) => {
for (const source of returnedReferences(callee).references)
continueWith(
source.node,
path === undefined
? undefined
: [
...source.projection.map((key) =>
key === null || typeof key === "object"
? null
: String(key),
),
...path,
],
);
};
if (!t.isIdentifier(root) && facts?.freshObject(root)) {
localIdentity?.(root, suffix);
for (const [source, path] of facts?.stores.get(root) ?? []) {
const selected =
suffix === undefined ||
path === undefined ||
path.every(
(key, index) =>
index >= suffix.length ||
key === null ||
suffix[index] === null ||
key === suffix[index],
);
if (
!selected ||
(suffix !== undefined &&
path !== undefined &&
suffix.length < path.length &&
!escapedContents)
)
const queuedBefore = pending.length;
const pathsBefore = result.size;
let resolvedIdentity = false;
try {
const { root, members } = electronMemberPath(current.node);
let suffix: AmbientProjection =
current.suffix === undefined
? undefined
: [...members, ...current.suffix];
if (expanded.has(root)) {
const previous = expanded.get(root);
if (previous === undefined) {
resolvedIdentity = true;
continue;
const remaining =
suffix === undefined || path === undefined
? undefined
: suffix.slice(path.length);
}
if (suffix !== undefined && previous.length === suffix.length) {
const joined: AmbientPath = previous.map((key, index) =>
key === suffix?.[index] ? key : null,
);
if (joined.every((key, index) => key === previous[index])) {
resolvedIdentity = true;
continue;
}
suffix = joined;
} else suffix = undefined;
if (!possibleWrites) {
const unresolved: AmbientResolution = {
paths: [],
ownership: "unknown",
unknownReasons: ["widened-projection"],
};
cached.set(node, unresolved);
return unresolved;
}
}
expanded.set(root, suffix);
if (suffix === undefined || suffix.includes(null))
unknownReasons.add("widened-projection");
// A widened projection is a possible write, never proof of an intrinsic.
if (suffix === undefined && !possibleWrites) continue;
const continueWith = (node: t.Node, path: AmbientProjection = suffix) =>
pending.push({
node: source.node,
readsAtSelf: true,
suffix:
remaining === undefined
node,
suffix: path,
...(current.readsAtSelf && { readsAtSelf: true }),
});
const continueReturned = (callee: t.Node, path: AmbientProjection) => {
const returned = returnedReferences(callee);
// Returned references retain possible source-local values, not a
// completeness proof for every runtime callable alternative.
unknownReasons.add("unresolved-call");
for (const source of returned.references)
continueWith(
source.node,
path === undefined
? undefined
: [
...source.projection.map((key) =>
@@ -241,235 +235,311 @@ export const createAmbientPathResolver = (
? null
: String(key),
),
...remaining,
...path,
],
});
}
}
if (
t.isMetaProperty(root) &&
root.meta.name === "import" &&
root.property.name === "meta"
) {
retain(["import-meta", ...(suffix ?? [])]);
continue;
}
if (t.isIdentifier(root)) {
// The wrapper module object is distinct from globalThis.module. Keep
// its identity through the same alias/projection owner used for writes.
if (isUnshadowedGlobal(root, state, "module")) {
retain(["commonjs-module", ...(suffix ?? [])]);
continue;
}
if (globalObjectName(root, state) !== undefined) {
retain(["global", ...(suffix ?? [])]);
continue;
}
if (isUnshadowedGlobal(root, state, root.name)) {
retain(["global", root.name, ...(suffix ?? [])]);
continue;
}
const binding = resolveSemanticBindingState(state, root, root.name);
if (binding === undefined) continue;
const stable = possibleWrites
? undefined
: semanticStableInitializer(binding, state);
const readAt = current.readsAtSelf ? root : capture;
const selected =
!possibleWrites || readAt === undefined
? binding
: semanticBindingAtRead(binding, readAt, state.parentsByNode)
.binding;
const initializers = possibleWrites
? [...selected.initializers, ...selected.referenceInitializers]
: stable === undefined
? []
: [stable];
for (const initializer of initializers) {
if (semanticReferenceSourcesInactive(initializer, state)) continue;
// Pattern assignments share the source selection owner with member
// effects: copying a container preserves its children, not itself.
const path = semanticCopiedReferencePath(
initializer,
suffix ?? [null],
escapedContents ? "escape" : "identity",
);
if (path === null) continue;
pending.push({
node: initializer.node,
readsAtSelf: true,
suffix:
suffix === undefined ||
semanticReferenceIterationUnknown(initializer, state)
? undefined
: path.map((key) =>
key === null || typeof key === "object"
? null
: String(key),
),
});
}
continue;
}
if (
possibleWrites &&
t.isNewExpression(root) &&
(suffix?.[0] === "__proto__" || suffix?.[0] === "constructor")
) {
continueWith(
root.callee,
suffix[0] === "__proto__"
? ["prototype", ...suffix.slice(1)]
: suffix.slice(1),
);
continue;
}
const prototypeTarget = possibleWrites
? facts?.prototypeTarget(root)
: undefined;
if (prototypeTarget !== undefined) {
continueWith(
prototypeTarget,
suffix === undefined ? undefined : ["__proto__", ...suffix],
);
continue;
}
if (
possibleWrites &&
(t.isCallExpression(root) ||
t.isOptionalCallExpression(root) ||
t.isNewExpression(root) ||
t.isTaggedTemplateExpression(root) ||
(escapedContents && (t.isFunction(root) || t.isClass(root))))
) {
continueReturned(
t.isFunction(root) || t.isClass(root)
? root
: t.isTaggedTemplateExpression(root)
? root.tag
: root.callee,
suffix,
);
continue;
}
if (possibleWrites && t.isConditionalExpression(root)) {
continueWith(root.consequent);
continueWith(root.alternate);
continue;
}
if (possibleWrites && t.isLogicalExpression(root)) {
continueWith(root.left);
continueWith(root.right);
continue;
}
if (possibleWrites && t.isSequenceExpression(root)) {
const value = root.expressions.at(-1);
if (value !== undefined) continueWith(value);
continue;
}
if (
possibleWrites &&
t.isAssignmentExpression(root) &&
root.operator === "="
) {
continueWith(root.right);
continue;
}
const key = suffix?.[0];
// Container escapes reuse the finite worklist, including alias cycles.
if (escapedContents && suffix?.length === 0) {
if (t.isObjectExpression(root)) {
for (const property of root.properties)
if (t.isSpreadElement(property))
// A fresh copy exposes selected children, not its source container.
continueWith(property.argument, [null]);
else if (
t.isObjectProperty(property) &&
t.isExpression(property.value)
)
continueWith(property.value, []);
else if (t.isObjectMethod(property) && property.kind === "get")
continueReturned(property, []);
continue;
}
if (t.isArrayExpression(root)) {
for (const element of root.elements)
if (t.isSpreadElement(element)) continueWith(element.argument, []);
else if (t.isExpression(element)) continueWith(element, []);
continue;
}
}
if (suffix !== undefined && key === undefined) continue;
if (t.isObjectExpression(root)) {
if (possibleWrites) {
for (const property of root.properties) {
if (t.isSpreadElement(property)) continueWith(property.argument);
else if (
(t.isObjectProperty(property) &&
t.isExpression(property.value)) ||
(t.isObjectMethod(property) && property.kind === "get")
) {
const ownKey = semanticStaticPropertyKey(
property.key,
property.computed,
);
if (
suffix === undefined ||
key === null ||
ownKey === null ||
ownKey === key
)
if (t.isObjectMethod(property))
continueReturned(property, suffix?.slice(1));
else if (t.isExpression(property.value))
continueWith(property.value, suffix?.slice(1));
}
);
};
if (!t.isIdentifier(root) && facts?.freshObject(root)) {
localIdentity?.(root, suffix);
// The allocation owns itself; a projected child needs its own proof.
if (suffix?.length === 0) {
hasLocalIdentity = true;
resolvedIdentity = true;
}
for (const [source, path] of facts?.stores.get(root) ?? []) {
const selected =
suffix === undefined ||
path === undefined ||
path.every(
(key, index) =>
index >= suffix.length ||
key === null ||
suffix[index] === null ||
key === suffix[index],
);
if (
!selected ||
(suffix !== undefined &&
path !== undefined &&
suffix.length < path.length &&
!escapedContents)
)
continue;
const remaining =
suffix === undefined || path === undefined
? undefined
: suffix.slice(path.length);
pending.push({
node: source.node,
readsAtSelf: true,
suffix:
remaining === undefined
? undefined
: [
...source.projection.map((key) =>
key === null || typeof key === "object"
? null
: String(key),
),
...remaining,
],
});
}
} else if (
suffix !== undefined &&
key !== null &&
root.properties.every(
(property) =>
t.isObjectProperty(property) &&
semanticStaticPropertyKey(property.key, property.computed) !==
null,
)
) {
const property = root.properties.findLast(
(property) =>
t.isObjectProperty(property) &&
semanticStaticPropertyKey(property.key, property.computed) ===
key,
);
if (t.isObjectProperty(property) && t.isExpression(property.value))
continueWith(property.value, suffix.slice(1));
}
} else if (t.isArrayExpression(root)) {
if (suffix === undefined) {
for (const element of root.elements)
if (t.isSpreadElement(element)) continueWith(element.argument);
else if (t.isExpression(element)) continueWith(element);
} else if (!root.elements.some(t.isSpreadElement)) {
const index = Number(key);
if (key === null && possibleWrites) {
if (
t.isMetaProperty(root) &&
root.meta.name === "import" &&
root.property.name === "meta"
) {
retain(["import-meta", ...(suffix ?? [])]);
resolvedIdentity = true;
continue;
}
if (t.isIdentifier(root)) {
// The wrapper module object is distinct from globalThis.module. Keep
// its identity through the same alias/projection owner used for writes.
if (isUnshadowedGlobal(root, state, "module")) {
retain(["commonjs-module", ...(suffix ?? [])]);
resolvedIdentity = true;
continue;
}
if (globalObjectName(root, state) !== undefined) {
retain(["global", ...(suffix ?? [])]);
resolvedIdentity = true;
continue;
}
if (isUnshadowedGlobal(root, state, root.name)) {
retain(["global", root.name, ...(suffix ?? [])]);
resolvedIdentity = true;
continue;
}
const binding = resolveSemanticBindingState(state, root, root.name);
if (binding === undefined) continue;
const stable = possibleWrites
? undefined
: semanticStableInitializer(binding, state);
const readAt = current.readsAtSelf ? root : capture;
const atRead =
possibleWrites && readAt !== undefined
? semanticBindingAtRead(binding, readAt, state.parentsByNode)
: undefined;
const selected = atRead?.binding ?? binding;
if (possibleWrites && atRead?.hasDefiniteInitializer === false)
unknownReasons.add("unresolved-value");
const initializers = possibleWrites
? [...selected.initializers, ...selected.referenceInitializers]
: stable === undefined
? []
: [stable];
for (const initializer of initializers) {
if (semanticReferenceSourcesInactive(initializer, state)) continue;
// Pattern assignments share the source selection owner with member
// effects: copying a container preserves its children, not itself.
const path = semanticCopiedReferencePath(
initializer,
suffix ?? [null],
escapedContents ? "escape" : "identity",
);
if (path === null) continue;
pending.push({
node: initializer.node,
readsAtSelf: true,
suffix:
suffix === undefined ||
semanticReferenceIterationUnknown(initializer, state)
? undefined
: path.map((key) =>
key === null || typeof key === "object"
? null
: String(key),
),
});
}
continue;
}
if (
possibleWrites &&
t.isNewExpression(root) &&
(suffix?.[0] === "__proto__" || suffix?.[0] === "constructor")
) {
continueWith(
root.callee,
suffix[0] === "__proto__"
? ["prototype", ...suffix.slice(1)]
: suffix.slice(1),
);
continue;
}
const prototypeTarget = possibleWrites
? facts?.prototypeTarget(root)
: undefined;
if (prototypeTarget !== undefined) {
continueWith(
prototypeTarget,
suffix === undefined ? undefined : ["__proto__", ...suffix],
);
continue;
}
if (
possibleWrites &&
(t.isCallExpression(root) ||
t.isOptionalCallExpression(root) ||
t.isNewExpression(root) ||
t.isTaggedTemplateExpression(root) ||
(escapedContents && (t.isFunction(root) || t.isClass(root))))
) {
continueReturned(
t.isFunction(root) || t.isClass(root)
? root
: t.isTaggedTemplateExpression(root)
? root.tag
: root.callee,
suffix,
);
continue;
}
if (possibleWrites && t.isConditionalExpression(root)) {
continueWith(root.consequent);
continueWith(root.alternate);
continue;
}
if (possibleWrites && t.isLogicalExpression(root)) {
continueWith(root.left);
continueWith(root.right);
continue;
}
if (possibleWrites && t.isSequenceExpression(root)) {
const value = root.expressions.at(-1);
if (value !== undefined) continueWith(value);
continue;
}
if (
possibleWrites &&
t.isAssignmentExpression(root) &&
root.operator === "="
) {
continueWith(root.right);
continue;
}
const key = suffix?.[0];
// Container escapes reuse the finite worklist, including alias cycles.
if (escapedContents && suffix?.length === 0) {
if (t.isObjectExpression(root)) {
for (const property of root.properties)
if (t.isSpreadElement(property))
// A fresh copy exposes selected children, not its source container.
continueWith(property.argument, [null]);
else if (
t.isObjectProperty(property) &&
t.isExpression(property.value)
)
continueWith(property.value, []);
else if (t.isObjectMethod(property) && property.kind === "get")
continueReturned(property, []);
continue;
}
if (t.isArrayExpression(root)) {
for (const element of root.elements)
if (t.isSpreadElement(element))
continueWith(element.argument, []);
else if (t.isExpression(element)) continueWith(element, []);
continue;
}
}
if (suffix !== undefined && key === undefined) continue;
if (t.isObjectExpression(root)) {
if (possibleWrites) {
for (const property of root.properties) {
if (t.isSpreadElement(property)) continueWith(property.argument);
else if (
(t.isObjectProperty(property) &&
t.isExpression(property.value)) ||
(t.isObjectMethod(property) && property.kind === "get")
) {
const ownKey = semanticStaticPropertyKey(
property.key,
property.computed,
);
if (
suffix === undefined ||
key === null ||
ownKey === null ||
ownKey === key
)
if (t.isObjectMethod(property))
continueReturned(property, suffix?.slice(1));
else if (t.isExpression(property.value))
continueWith(property.value, suffix?.slice(1));
}
}
} else if (
suffix !== undefined &&
key !== null &&
root.properties.every(
(property) =>
t.isObjectProperty(property) &&
semanticStaticPropertyKey(property.key, property.computed) !==
null,
)
) {
const property = root.properties.findLast(
(property) =>
t.isObjectProperty(property) &&
semanticStaticPropertyKey(property.key, property.computed) ===
key,
);
if (t.isObjectProperty(property) && t.isExpression(property.value))
continueWith(property.value, suffix.slice(1));
}
} else if (t.isArrayExpression(root)) {
if (suffix === undefined) {
for (const element of root.elements)
if (t.isSpreadElement(element)) continueWith(element.argument);
else if (t.isExpression(element)) continueWith(element);
} else if (!root.elements.some(t.isSpreadElement)) {
const index = Number(key);
if (key === null && possibleWrites) {
for (const element of root.elements)
if (t.isExpression(element))
continueWith(element, suffix.slice(1));
} else if (
key !== null &&
Number.isInteger(index) &&
index >= 0 &&
String(index) === key
) {
const element = root.elements[index];
if (t.isExpression(element))
continueWith(element, suffix.slice(1));
} else if (
key !== null &&
Number.isInteger(index) &&
index >= 0 &&
String(index) === key
) {
const element = root.elements[index];
if (t.isExpression(element)) continueWith(element, suffix.slice(1));
}
}
}
} finally {
if (
!resolvedIdentity &&
pending.length === queuedBefore &&
result.size === pathsBefore
)
unknownReasons.add("unresolved-value");
}
}
const paths = [...result.values()];
if (!possibleWrites) cached.set(node, paths);
return paths;
if (paths.length > 0 && hasLocalIdentity)
unknownReasons.add("mixed-identities");
const resolution: AmbientResolution = {
paths,
ownership:
unknownReasons.size > 0
? "unknown"
: paths.length > 0
? "ambient"
: hasLocalIdentity
? "local"
: "unknown",
unknownReasons: [...unknownReasons],
};
if (!possibleWrites) cached.set(node, resolution);
return resolution;
};
};
@@ -503,7 +573,7 @@ export function* indexJavaScriptAmbientWritesSteps(
>();
const interop = createSemanticModuleInterop(state, {
intrinsicPath: (node) => {
const [path] = ambientReads(node);
const [path] = ambientReads(node).paths;
return path?.[0] === "global" && path.every((key) => key !== null)
? ["intrinsic", ...(path.slice(1) as readonly string[])]
: undefined;
@@ -640,17 +710,8 @@ export function* indexJavaScriptAmbientWritesSteps(
}
for (const source of storedReferences) {
if (source.target === undefined) continue;
let local = false;
const ambient = ambientWrites(
source.target.object,
source.mutation,
false,
[],
() => {
local = true;
},
);
if (!local || ambient.length > 0) {
const receiver = ambientWrites(source.target.object, source.mutation);
if (receiver.ownership !== "local") {
state.escapingReferenceStores.add(source.target);
escapes.push({
node: source.mutation,
@@ -668,7 +729,7 @@ export function* indexJavaScriptAmbientWritesSteps(
const paths =
target === undefined
? [path]
: ambientWrites(target.node, target.capture).map((identity) => [
: ambientWrites(target.node, target.capture).paths.map((identity) => [
...identity,
...path.slice(2),
]);
@@ -677,7 +738,7 @@ export function* indexJavaScriptAmbientWritesSteps(
}
}
for (const { node, target, browserReceiver, projection } of escapes)
for (const path of ambientWrites(target, node, true, projection))
for (const path of ambientWrites(target, node, true, projection).paths)
// Only proven browser APIs keep their global receiver from user code.
if (!(browserReceiver && path.length === 1 && path[0] === "global")) {
retainSemanticAmbientEffect(state, "escape", path, node);
@@ -283,7 +283,7 @@ const visitSemanticReferenceEffectsAtSite = (
} else if (lookup.kind === "ambient" || lookup.kind === "uncertain-ambient") {
for (const node of state.ambientBindingWrites.get(root.name) ?? [])
if (!retain("ambient-write", node)) return metadata;
const ambientRoots = createAmbientPathResolver(state, false)(root);
const ambientRoots = createAmbientPathResolver(state, false)(root).paths;
for (const ambientRoot of ambientRoots) {
const selectedPath = [...ambientRoot, ...path];
for (const [kind, effects] of [
@@ -688,7 +688,7 @@ export function* collectSemanticMemberMutationsSteps(
current.path.map((key) =>
key === null || typeof key === "object" ? null : String(key),
),
))
).paths)
if (retainSemanticAmbientEffect(state, effect, path, mutation)) {
recordedEffectCount += 1;
clearSemanticValueCaches(state);
@@ -1810,7 +1810,7 @@ const observableMutationPaths = (
["globalThis", "global", "window", "self"].includes(expression.name)
)
(observer.origins ??= new Set()).add("ambient");
else if (ambientPaths(expression).length > 0)
else if (ambientPaths(expression).paths.length > 0)
(observer.origins ??= new Set()).add("opaque");
} else if (
t.isMemberExpression(expression) ||
@@ -63,7 +63,7 @@ export const createSemanticOpaqueGlobalObserver = (
let invocationSite: t.Node | undefined;
const interop = createSemanticModuleInterop(state, {
intrinsicPath: (node) => {
const paths = ambientPaths(node, invocationSite);
const paths = ambientPaths(node, invocationSite).paths;
const path = paths.find((path) => path[1] === "eval") ?? paths[0];
if (path?.[0] !== "global" || path.some((key) => key === null))
return undefined;
@@ -37,6 +37,8 @@ it.each([
'const box = {}; box.value = { name: "Alice" }; inspect(box); new Map().get("/accounts")',
'patch(() => ({ name: "Alice" })); new Map().get("/accounts")',
'const box = {}; box.prototype = Map.prototype; new Map().get("/accounts")',
'function expose() { const holder = { child: {} }; holder.child.prototype = Map.prototype; } new Map().get("/accounts")',
'const box = flag ? {} : {}; box.prototype = Map.prototype; new Map().get("/accounts")',
'const box = {}; const alias = box; alias.prototype = Map.prototype; inspect({}); new Map().get("/accounts")',
'const box = {}; box.make = () => Map.prototype; new Map().get("/accounts")',
'let box = {}; const first = box; box = {}; box.p = Map.prototype; patch(first); new Map().get("/accounts")',
@@ -84,6 +86,15 @@ it.each([
'const box = { set prototype(value) { patch(value); } }; box.prototype = Map.prototype; new Map().get("/accounts")',
'const box = new ExternalBox(); box.prototype = Map.prototype; new Map().get("/accounts")',
'function expose(box) { box.prototype = Map.prototype; } new Map().get("/accounts")',
'function expose(box = {}) { box.prototype = Map.prototype; } new Map().get("/accounts")',
'function expose(external, flag) { const box = flag ? {} : external; box.prototype = Map.prototype; } new Map().get("/accounts")',
'function expose(external) { const holder = { child: external }; holder.child.prototype = Map.prototype; } new Map().get("/accounts")',
'function expose(key) { const holder = { child: {} }; holder[key].prototype = Map.prototype; } new Map().get("/accounts")',
'function expose(key) { const holder = [{}]; holder[key].prototype = Map.prototype; } new Map().get("/accounts")',
'const box = flag ? {} : external(); box.prototype = Map.prototype; new Map().get("/accounts")',
'function expose(external, flag) { const make = flag ? () => ({}) : external; const box = make(); box.prototype = Map.prototype; } new Map().get("/accounts")',
'import external from "./external.mjs"; const box = flag ? {} : external; box.prototype = Map.prototype; new Map().get("/accounts")',
'let box; if (flag) box = {}; box.prototype = Map.prototype; new Map().get("/accounts")',
'const factory = { make() { return Map.prototype; } }; factory.make().get = fetch; new Map().get("/accounts")',
'new Map().__proto__.get = fetch; new Map().get("/accounts")',
'new Map().constructor.prototype.get = fetch; new Map().get("/accounts")',