diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 37905e1047c..a8ba45b8825 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13472,10 +13472,14 @@ namespace ts { } function isInParameterInitializerBeforeContainingFunction(node: Node) { + let inBindingInitializer = false; while (node.parent && !isFunctionLike(node.parent)) { - if (node.parent.kind === SyntaxKind.Parameter && (node.parent).initializer === node) { + if (isParameter(node.parent) && (inBindingInitializer || node.parent.initializer === node)) { return true; } + if (isBindingElement(node.parent) && node.parent.initializer === node) { + inBindingInitializer = true; + } node = node.parent; } diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index e8dfcbc1e94..35d35b40826 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -3709,7 +3709,7 @@ namespace ts { while (statementOffset < numStatements) { const statement = source[statementOffset]; if (getEmitFlags(statement) & EmitFlags.CustomPrologue) { - target.push(visitor ? visitNode(statement, visitor, isStatement) : statement); + append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); } else { break; diff --git a/tests/baselines/reference/expressionsForbiddenInParameterInitializers.errors.txt b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.errors.txt new file mode 100644 index 00000000000..605b6d78ea3 --- /dev/null +++ b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/bar.ts(1,35): error TS2524: 'await' expressions cannot be used in a parameter initializer. +tests/cases/compiler/bar.ts(4,31): error TS2523: 'yield' expressions cannot be used in a parameter initializer. + + +==== tests/cases/compiler/bar.ts (2 errors) ==== + export async function foo({ foo = await import("./bar") }) { + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2524: 'await' expressions cannot be used in a parameter initializer. + } + + export function* foo2({ foo = yield "a" }) { + ~~~~~~~~~ +!!! error TS2523: 'yield' expressions cannot be used in a parameter initializer. + } + \ No newline at end of file diff --git a/tests/baselines/reference/expressionsForbiddenInParameterInitializers.js b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.js new file mode 100644 index 00000000000..d66b3c8e06d --- /dev/null +++ b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.js @@ -0,0 +1,76 @@ +//// [bar.ts] +export async function foo({ foo = await import("./bar") }) { +} + +export function* foo2({ foo = yield "a" }) { +} + + +//// [bar.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +function foo(_a) { + var _b = _a.foo, foo = _b === void 0 ? yield Promise.resolve().then(function () { return require("./bar"); }) : _b; + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_c) { + return [2 /*return*/]; + }); + }); +} +exports.foo = foo; +function foo2(_a) { + var _b, foo, _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + _b = _a.foo; + if (!(_b === void 0)) return [3 /*break*/, 2]; + return [4 /*yield*/, "a"]; + case 1: + _c = _d.sent(); + return [3 /*break*/, 3]; + case 2: + _c = _b; + _d.label = 3; + case 3: + foo = _c; + return [2 /*return*/]; + } + }); +} +exports.foo2 = foo2; diff --git a/tests/baselines/reference/expressionsForbiddenInParameterInitializers.symbols b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.symbols new file mode 100644 index 00000000000..6ad101f3c17 --- /dev/null +++ b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/bar.ts === +export async function foo({ foo = await import("./bar") }) { +>foo : Symbol(foo, Decl(bar.ts, 0, 0)) +>foo : Symbol(foo, Decl(bar.ts, 0, 27)) +>"./bar" : Symbol("tests/cases/compiler/bar", Decl(bar.ts, 0, 0)) +} + +export function* foo2({ foo = yield "a" }) { +>foo2 : Symbol(foo2, Decl(bar.ts, 1, 1)) +>foo : Symbol(foo, Decl(bar.ts, 3, 23)) +} + diff --git a/tests/baselines/reference/expressionsForbiddenInParameterInitializers.types b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.types new file mode 100644 index 00000000000..1fd11b0513b --- /dev/null +++ b/tests/baselines/reference/expressionsForbiddenInParameterInitializers.types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/bar.ts === +export async function foo({ foo = await import("./bar") }) { +>foo : ({ foo }: { foo?: typeof "tests/cases/compiler/bar"; }) => Promise +>foo : typeof "tests/cases/compiler/bar" +>await import("./bar") : typeof "tests/cases/compiler/bar" +>import("./bar") : Promise +>"./bar" : "./bar" +} + +export function* foo2({ foo = yield "a" }) { +>foo2 : ({ foo }: { foo?: any; }) => IterableIterator +>foo : any +>yield "a" : any +>"a" : "a" +} + diff --git a/tests/cases/compiler/expressionsForbiddenInParameterInitializers.ts b/tests/cases/compiler/expressionsForbiddenInParameterInitializers.ts new file mode 100644 index 00000000000..ea4dce15408 --- /dev/null +++ b/tests/cases/compiler/expressionsForbiddenInParameterInitializers.ts @@ -0,0 +1,7 @@ +// @lib: es6 +// @filename: bar.ts +export async function foo({ foo = await import("./bar") }) { +} + +export function* foo2({ foo = yield "a" }) { +}