mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 10:30:01 +08:00
fix(codemode): bind generator parameters at the call, not the first next() (#50489)
This commit is contained in:
@@ -150,8 +150,8 @@ ultimate source of truth. Upstream test262 files run verbatim from `test/test262
|
||||
- [x] Redeclaring a function in the same scope, or alongside a `var`, is allowed: the last declaration wins.
|
||||
- [x] Generator functions have their own `prototype` (inheriting the shared generator prototype), so
|
||||
`g() instanceof g` holds. Plain functions have none, since they cannot construct.
|
||||
- [ ] Generator and async generator functions evaluate parameter defaults and destructuring at the first `next()`
|
||||
rather than at the call, so their errors are not thrown synchronously.
|
||||
- [x] Generator and async generator functions bind parameters (defaults, destructuring) at the call and defer only the
|
||||
body to the first `next()`, so a bad argument throws synchronously from the call site, as in JS.
|
||||
- [x] Synchronous and async generator declarations/expressions, `yield`, and `yield*`, including lazy bodies,
|
||||
`next(value)`, `return(value)`, `throw(value)`, exhaustion, promise adoption, async request ordering,
|
||||
`try`/`catch`/`finally`, and sync/async iterator symbols. Async `yield*` awaits values while adapting a sync
|
||||
|
||||
@@ -1659,14 +1659,14 @@ class Frame<R> {
|
||||
const depth = Math.max(self.depth, site.depth) + 1
|
||||
if (depth > MAX_CALL_DEPTH) throw rangeError("Maximum call stack size exceeded", node)
|
||||
const invocation = new Frame(this.ctx, new ScopeStack([...fn.capturedScopes, new Map()]), depth)
|
||||
const run = Effect.gen(function* () {
|
||||
// Seed all parameters first so defaults cannot fall through to same-named outer bindings.
|
||||
const paramScope = invocation.scopes.current()
|
||||
for (const parameter of fn.parameters) {
|
||||
for (const name of collectPatternNames(parameter)) {
|
||||
paramScope.set(name, { mutable: true, value: undefined, initialized: false })
|
||||
}
|
||||
// Seed all parameters first so defaults cannot fall through to same-named outer bindings.
|
||||
const paramScope = invocation.scopes.current()
|
||||
for (const parameter of fn.parameters) {
|
||||
for (const name of collectPatternNames(parameter)) {
|
||||
paramScope.set(name, { mutable: true, value: undefined, initialized: false })
|
||||
}
|
||||
}
|
||||
const bind = Effect.gen(function* () {
|
||||
for (const [index, parameter] of fn.parameters.entries()) {
|
||||
if (parameter.type === "RestElement") {
|
||||
yield* invocation.declarePattern(
|
||||
@@ -1680,7 +1680,8 @@ class Frame<R> {
|
||||
}
|
||||
yield* invocation.declarePattern(parameter, args[index], true, parameter, true)
|
||||
}
|
||||
|
||||
})
|
||||
const body = Effect.gen(function* () {
|
||||
if (fn.body.type === "BlockStatement") {
|
||||
invocation.scopes.push()
|
||||
invocation.hoistVars(fn.body.body, paramScope)
|
||||
@@ -1690,7 +1691,9 @@ class Frame<R> {
|
||||
|
||||
return yield* invocation.evaluateExpression(fn.body)
|
||||
})
|
||||
if (fn.generator) return Effect.succeed(this.createGenerator(invocation, run, fn))
|
||||
// Generators bind parameters at the call and defer only the body to the first `next()`, as in JS.
|
||||
if (fn.generator) return Effect.map(bind, () => this.createGenerator(invocation, body, fn))
|
||||
const run = Effect.andThen(bind, body)
|
||||
if (!fn.async) return run
|
||||
return this.ctx.pending.createWithSelf((self) =>
|
||||
Effect.flatMap(run, (value) => resolvePromiseValue(invocation.ctx, value, self)),
|
||||
|
||||
@@ -23,6 +23,27 @@ const value = async (code: string) => {
|
||||
}
|
||||
|
||||
describe("confined generators", () => {
|
||||
test("parameters are bound at the call; only the body waits for next()", async () => {
|
||||
expect(
|
||||
await value(`
|
||||
const log = []
|
||||
function* g(a = log.push("param")) { log.push("body"); yield a }
|
||||
const it = g()
|
||||
log.push("created")
|
||||
it.next()
|
||||
function* bad({ x } = null) { yield x }
|
||||
async function* asyncBad({ x } = null) { yield x }
|
||||
let failures = []
|
||||
try { bad() } catch (error) { failures.push(error.constructor.name) }
|
||||
try { asyncBad() } catch (error) { failures.push(error.constructor.name) }
|
||||
return [log, failures]
|
||||
`),
|
||||
).toEqual([
|
||||
["param", "created", "body"],
|
||||
["TypeError", "TypeError"],
|
||||
])
|
||||
})
|
||||
|
||||
// test/built-ins/GeneratorPrototype/next/return-yield-expr.js
|
||||
test("is lazy and preserves next(value), nested suspension, return, and exhaustion", async () => {
|
||||
expect(
|
||||
|
||||
@@ -234,53 +234,8 @@ built-ins/Iterator/prototype/drop/limit-tonumber-throws.js # Expected a Test262
|
||||
built-ins/Iterator/prototype/drop/limit-tonumber.js # Iterator.prototype.drop expects a non-negative count, received NaN.
|
||||
built-ins/Iterator/prototype/take/limit-tonumber-throws.js # Expected a Test262Error but got a RangeError
|
||||
built-ins/Iterator/prototype/take/limit-tonumber.js # Iterator.prototype.take expects a non-negative count, received NaN.
|
||||
language/statements/async-generator/dflt-params-abrupt.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dflt-params-ref-later.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dflt-params-ref-self.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-init-iter-get-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-ary-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-elision-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-rest-id-elision-next-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/ary-ptrn-rest-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-init-iter-get-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-ary-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-obj-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-elision-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-rest-id-elision-next-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-ary-ptrn-rest-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-init-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-init-undefined.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-list-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-ary-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-eval-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-obj-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/dflt-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-init-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-init-undefined.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-list-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-ary-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-eval-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/async-generator/return-undefined-implicit-and-explicit.js # Actual ["tick 1", "tick 2", "g1 ret", "g2 ret", "g3 ret", "g4 ret"] and expected ["tick 1", "g1 ret"
|
||||
language/statements/const/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/for-await-of/async-func-decl-dstr-obj-empty-bool.js # TypeError: Object destructuring requires a data object or array value, received a boolean.
|
||||
@@ -331,53 +286,8 @@ language/statements/function/S13.2_A4_T1.js # Unknown identifier '…'.
|
||||
language/statements/function/S13.2_A4_T2.js # #1: typeof __gunc.prototype === '…'. Actual: typeof __gunc.prototype ===undefined
|
||||
language/statements/function/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/function/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dflt-params-abrupt.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dflt-params-ref-later.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dflt-params-ref-self.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-init-iter-get-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-ary-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-obj-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elem-obj-val-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-elision-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-rest-id-elision-next-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/ary-ptrn-rest-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-init-iter-get-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-ary-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-obj-val-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elem-obj-val-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-elision-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-rest-id-elision-next-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-ary-ptrn-rest-id-iter-step-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-init-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-init-undefined.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-list-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-ary-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-eval-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-obj-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/dflt-obj-ptrn-prop-obj-value-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-init-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-init-undefined.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-list-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-ary-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-eval-err.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-id-init-throws.js # Expected a Test262Error to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-id-init-unresolvable.js # Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-obj-value-null.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/generators/dstr/obj-ptrn-prop-obj-value-undef.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/labeled/value-await-non-module.js # Failed to parse TypeScript: Expression expected.
|
||||
language/statements/let/dstr/ary-init-iter-get-err-array-prototype.js # Expected a TypeError to be thrown but no exception was thrown at all
|
||||
language/statements/return/S12.9_A1_T1.js # expected SyntaxError but the program ran
|
||||
|
||||
Reference in New Issue
Block a user