refactor(codemode): rename Sandbox terminology to CodeMode (#36768)

This commit is contained in:
Aiden Cline 2026-07-13 16:38:11 -05:00 committed by GitHub
commit ecb5754f4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 257 additions and 257 deletions

View file

@ -73,14 +73,14 @@ import {
valueConstructors,
} from "../stdlib/value.js"
import {
isSandboxValue,
SandboxDate,
SandboxMap,
SandboxPromise,
SandboxRegExp,
SandboxSet,
SandboxURL,
SandboxURLSearchParams,
isCodeModeValue,
CodeModeDate,
CodeModeMap,
CodeModePromise,
CodeModeRegExp,
CodeModeSet,
CodeModeURL,
CodeModeURLSearchParams,
} from "../values.js"
const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => {
@ -91,24 +91,24 @@ const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean =>
if (rhs instanceof GlobalNamespace) {
switch (rhs.name) {
case "Date":
return lhs instanceof SandboxDate
return lhs instanceof CodeModeDate
case "RegExp":
return lhs instanceof SandboxRegExp
return lhs instanceof CodeModeRegExp
case "Map":
return lhs instanceof SandboxMap
return lhs instanceof CodeModeMap
case "Set":
return lhs instanceof SandboxSet
return lhs instanceof CodeModeSet
case "URL":
return lhs instanceof SandboxURL
return lhs instanceof CodeModeURL
case "URLSearchParams":
return lhs instanceof SandboxURLSearchParams
return lhs instanceof CodeModeURLSearchParams
case "Array":
return Array.isArray(lhs)
case "Object":
return lhs !== null && (typeof lhs === "object" || typeofValue(lhs) === "function")
}
}
if (rhs instanceof PromiseNamespace) return lhs instanceof SandboxPromise
if (rhs instanceof PromiseNamespace) return lhs instanceof CodeModePromise
if (rhs instanceof CoercionFunction && (rhs.name === "Number" || rhs.name === "String" || rhs.name === "Boolean")) {
return false
}
@ -226,7 +226,7 @@ export class Interpreter<R> {
}
// The implicit async body adopts returned promises before copy-out.
if (value instanceof SandboxPromise) value = yield* self.settlePromise(value)
if (value instanceof CodeModePromise) value = yield* self.settlePromise(value)
return value
}).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())))
}
@ -235,16 +235,16 @@ export class Interpreter<R> {
private createToolCallPromise(
path: ReadonlyArray<string>,
args: Array<unknown>,
): Effect.Effect<SandboxPromise, never, R> {
): Effect.Effect<CodeModePromise, never, R> {
return this.createPromise(Effect.suspend(() => this.invokeTool(path, args)))
}
private createPromise(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<SandboxPromise, never, R> {
private createPromise(effect: Effect.Effect<unknown, unknown, R>): Effect.Effect<CodeModePromise, never, R> {
return this.promises.create(effect)
}
// Fiber exits make settlement idempotent; yielding prevents inline continuation.
private settlePromise(promise: SandboxPromise): Effect.Effect<unknown, unknown, never> {
private settlePromise(promise: CodeModePromise): Effect.Effect<unknown, unknown, never> {
const promises = this.promises
return Effect.suspend(() => {
promises.markObserved(promise)
@ -971,7 +971,7 @@ export class Interpreter<R> {
// Await always suspends, including for plain values.
const self = this
return Effect.flatMap(this.evaluateExpression(getNode(node, "argument")), (value) =>
value instanceof SandboxPromise ? self.settlePromise(value) : Effect.as(Effect.yieldNow, value),
value instanceof CodeModePromise ? self.settlePromise(value) : Effect.as(Effect.yieldNow, value),
)
}
case "NewExpression":
@ -1019,23 +1019,23 @@ export class Interpreter<R> {
throw unsupportedSyntax("NewExpression", node)
}
private constructDate(args: Array<unknown>): SandboxDate {
if (args.length === 0) return new SandboxDate(Date.now())
private constructDate(args: Array<unknown>): CodeModeDate {
if (args.length === 0) return new CodeModeDate(Date.now())
if (args.length === 1) {
const arg = args[0]
if (arg instanceof SandboxDate) return new SandboxDate(arg.time)
if (typeof arg === "number") return new SandboxDate(new Date(arg).getTime())
if (typeof arg === "string") return new SandboxDate(Date.parse(arg))
return new SandboxDate(Number.NaN)
if (arg instanceof CodeModeDate) return new CodeModeDate(arg.time)
if (typeof arg === "number") return new CodeModeDate(new Date(arg).getTime())
if (typeof arg === "string") return new CodeModeDate(Date.parse(arg))
return new CodeModeDate(Number.NaN)
}
const parts = args.map((arg) => coerceToNumber(arg))
return new SandboxDate(new Date(...(parts as [number, number])).getTime())
return new CodeModeDate(new Date(...(parts as [number, number])).getTime())
}
private constructRegExp(args: Array<unknown>, node: AstNode): SandboxRegExp {
private constructRegExp(args: Array<unknown>, node: AstNode): CodeModeRegExp {
const first = args[0]
const pattern =
first instanceof SandboxRegExp ? first.regex.source : first === undefined ? "" : coerceToString(first)
first instanceof CodeModeRegExp ? first.regex.source : first === undefined ? "" : coerceToString(first)
const flagsArg = args[1]
if (flagsArg !== undefined && typeof flagsArg !== "string") {
throw new InterpreterRuntimeError(
@ -1043,9 +1043,9 @@ export class Interpreter<R> {
node,
)
}
const flags = flagsArg ?? (first instanceof SandboxRegExp ? first.regex.flags : "")
const flags = flagsArg ?? (first instanceof CodeModeRegExp ? first.regex.flags : "")
try {
return new SandboxRegExp(pattern, flags)
return new CodeModeRegExp(pattern, flags)
} catch (error) {
const reason = regexFailureReason(error)
throw new InterpreterRuntimeError(
@ -1057,12 +1057,12 @@ export class Interpreter<R> {
}
}
private constructMap(init: unknown, node: AstNode): SandboxMap {
const target = new SandboxMap()
private constructMap(init: unknown, node: AstNode): CodeModeMap {
const target = new CodeModeMap()
if (init === undefined || init === null) return target
const entries = Array.isArray(init)
? init
: init instanceof SandboxMap
: init instanceof CodeModeMap
? Array.from(init.map.entries(), ([key, item]): Array<unknown> => [key, item])
: undefined
if (entries === undefined) {
@ -1080,12 +1080,12 @@ export class Interpreter<R> {
return target
}
private constructSet(init: unknown, node: AstNode): SandboxSet {
const target = new SandboxSet()
private constructSet(init: unknown, node: AstNode): CodeModeSet {
const target = new CodeModeSet()
if (init === undefined || init === null) return target
const items = Array.isArray(init)
? init
: init instanceof SandboxSet
: init instanceof CodeModeSet
? Array.from(init.set.values())
: typeof init === "string"
? Array.from(init)
@ -1097,7 +1097,7 @@ export class Interpreter<R> {
return target
}
private constructURL(args: Array<unknown>, node: AstNode): SandboxURL {
private constructURL(args: Array<unknown>, node: AstNode): CodeModeURL {
if (args.length === 0) {
throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as(
"TypeError",
@ -1106,7 +1106,7 @@ export class Interpreter<R> {
const input = urlArgument(args[0], "new URL input")
const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base")
try {
return new SandboxURL(new URL(input, base))
return new CodeModeURL(new URL(input, base))
} catch {
throw new InterpreterRuntimeError(
`new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`,
@ -1115,16 +1115,16 @@ export class Interpreter<R> {
}
}
private constructURLSearchParams(init: unknown, node: AstNode): SandboxURLSearchParams {
if (init === undefined) return new SandboxURLSearchParams(new URLSearchParams())
if (init instanceof SandboxURLSearchParams) {
return new SandboxURLSearchParams(new URLSearchParams(init.params))
private constructURLSearchParams(init: unknown, node: AstNode): CodeModeURLSearchParams {
if (init === undefined) return new CodeModeURLSearchParams(new URLSearchParams())
if (init instanceof CodeModeURLSearchParams) {
return new CodeModeURLSearchParams(new URLSearchParams(init.params))
}
if (typeof init === "string") return new SandboxURLSearchParams(new URLSearchParams(init))
if (typeof init === "string") return new CodeModeURLSearchParams(new URLSearchParams(init))
if (init === null || typeof init === "number" || typeof init === "boolean") {
return new SandboxURLSearchParams(new URLSearchParams(coerceToString(init)))
return new CodeModeURLSearchParams(new URLSearchParams(coerceToString(init)))
}
if (init instanceof SandboxMap) {
if (init instanceof CodeModeMap) {
return this.constructURLSearchParams(
Array.from(init.map.entries(), ([key, value]) => [key, value]),
node,
@ -1143,9 +1143,9 @@ export class Interpreter<R> {
string,
]
})
return new SandboxURLSearchParams(new URLSearchParams(entries))
return new CodeModeURLSearchParams(new URLSearchParams(entries))
}
if (isSandboxValue(init)) return new SandboxURLSearchParams(new URLSearchParams())
if (isCodeModeValue(init)) return new CodeModeURLSearchParams(new URLSearchParams())
const data = boundedData(init, "new URLSearchParams input")
if (data === null || typeof data !== "object") {
throw new InterpreterRuntimeError(
@ -1153,7 +1153,7 @@ export class Interpreter<R> {
node,
).as("TypeError")
}
return new SandboxURLSearchParams(
return new CodeModeURLSearchParams(
new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))),
)
}
@ -1176,7 +1176,7 @@ export class Interpreter<R> {
// Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
// Dates use string coercion for `+` and epoch time elsewhere.
const coerceOperand = (operand: unknown): unknown => {
if (operand instanceof SandboxDate) return operator === "+" ? coerceToString(operand) : operand.time
if (operand instanceof CodeModeDate) return operator === "+" ? coerceToString(operand) : operand.time
return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand
}
const bothObjects = lhs !== null && typeof lhs === "object" && rhs !== null && typeof rhs === "object"
@ -1261,7 +1261,7 @@ export class Interpreter<R> {
throw new InterpreterRuntimeError("Unary operators require data values in CodeMode.", node, "InvalidDataValue")
}
const operand =
value instanceof SandboxDate
value instanceof CodeModeDate
? value.time
: value !== null && typeof value === "object"
? coerceToString(value)
@ -1520,11 +1520,11 @@ export class Interpreter<R> {
})
if (!fn.async) return run
// The initial yield assigns `box.own` before the body can self-resolve.
const box: { own?: SandboxPromise } = {}
const box: { own?: CodeModePromise } = {}
return Effect.map(
this.createPromise(
Effect.flatMap(run, (value) => {
if (!(value instanceof SandboxPromise)) return Effect.succeed(value)
if (!(value instanceof CodeModePromise)) return Effect.succeed(value)
if (value === box.own) return Effect.fail(selfResolutionError())
return invocation.settlePromise(value)
}),
@ -1546,7 +1546,7 @@ export class Interpreter<R> {
if (property.type === "SpreadElement") {
const spread = yield* self.evaluateExpression(getNode(property, "argument"))
if (spread === null || spread === undefined || isSandboxValue(spread)) continue
if (spread === null || spread === undefined || isCodeModeValue(spread)) continue
if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) {
throw new InterpreterRuntimeError(
"Object spread requires a data object in CodeMode.",
@ -1748,28 +1748,28 @@ export class Interpreter<R> {
if (objectValue.name === "String" && stringStatics.has(key)) return new GlobalMethodReference("String", key)
}
if (objectValue instanceof SandboxDate) {
if (objectValue instanceof CodeModeDate) {
if (typeof key === "string" && dateMethods.has(key)) return new IntrinsicReference(objectValue, key)
return new ComputedValue(undefined)
}
if (objectValue instanceof SandboxRegExp) {
if (objectValue instanceof CodeModeRegExp) {
if (typeof key === "string" && regexpProperties.has(key)) {
return new ComputedValue((objectValue.regex as unknown as Record<string, unknown>)[key])
}
if (typeof key === "string" && regexpMethods.has(key)) return new IntrinsicReference(objectValue, key)
return new ComputedValue(undefined)
}
if (objectValue instanceof SandboxMap) {
if (objectValue instanceof CodeModeMap) {
if (key === "size") return new ComputedValue(objectValue.map.size)
if (typeof key === "string" && mapMethods.has(key)) return new IntrinsicReference(objectValue, key)
return new ComputedValue(undefined)
}
if (objectValue instanceof SandboxSet) {
if (objectValue instanceof CodeModeSet) {
if (key === "size") return new ComputedValue(objectValue.set.size)
if (typeof key === "string" && setMethods.has(key)) return new IntrinsicReference(objectValue, key)
return new ComputedValue(undefined)
}
if (objectValue instanceof SandboxURL) {
if (objectValue instanceof CodeModeURL) {
if (key === "searchParams") {
return new ComputedValue(objectValue.searchParams)
}
@ -1777,7 +1777,7 @@ export class Interpreter<R> {
if (typeof key === "string" && urlProperties.has(key)) return { target: objectValue, key }
return new ComputedValue(undefined)
}
if (objectValue instanceof SandboxURLSearchParams) {
if (objectValue instanceof CodeModeURLSearchParams) {
if (key === "size") return new ComputedValue(objectValue.params.size)
if (typeof key === "string" && urlSearchParamsMethods.has(key)) {
return new IntrinsicReference(objectValue, key)
@ -1786,7 +1786,7 @@ export class Interpreter<R> {
}
// Reject unknown promise properties so a missing await cannot hide.
if (objectValue instanceof SandboxPromise) {
if (objectValue instanceof CodeModePromise) {
if (key === "then" || key === "catch" || key === "finally") {
return new PromiseInstanceMethodReference(objectValue, key)
}
@ -1851,7 +1851,7 @@ export class Interpreter<R> {
}
return reference.key === "length" ? reference.target.length : reference.target[Number(reference.key)]
}
if (reference.target instanceof SandboxURL) {
if (reference.target instanceof CodeModeURL) {
return (reference.target.url as unknown as Record<string, unknown>)[String(reference.key)]
}
return reference.target[String(reference.key)]
@ -1891,7 +1891,7 @@ export class Interpreter<R> {
}
const key = Array.isArray(reference.target) ? Number(reference.key) : String(reference.key)
const current =
reference.target instanceof SandboxURL
reference.target instanceof CodeModeURL
? (reference.target.url as unknown as Record<string, unknown>)[key]
: (reference.target as Record<PropertyKey, unknown>)[key]
const { write, next, result } = yield* compute(current)
@ -1915,7 +1915,7 @@ export class Interpreter<R> {
target[index] = next
return
}
if (reference.target instanceof SandboxURL) {
if (reference.target instanceof CodeModeURL) {
const property = key as string
if (!urlWritableProperties.has(property)) {
throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError")