diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a18c3c45680..3113b56557d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13771,7 +13771,7 @@ namespace ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (!hasRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { + if (!hasDeclaredRestParameter(node) || isInAmbientContext(node) || nodeIsMissing((node).body)) { return; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 5c0b249aa4c..8bcdd4c8201 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4467,7 +4467,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } function emitRestParameter(node: FunctionLikeDeclaration) { - if (languageVersion < ScriptTarget.ES6 && hasRestParameter(node)) { + if (languageVersion < ScriptTarget.ES6 && hasDeclaredRestParameter(node)) { const restIndex = node.parameters.length - 1; const restParam = node.parameters[restIndex]; @@ -4624,7 +4624,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge if (node) { const parameters = node.parameters; const skipCount = node.parameters.length && (node.parameters[0].name).text === "this" ? 1 : 0; - const omitCount = languageVersion < ScriptTarget.ES6 && hasRestParameter(node) ? 1 : 0; + const omitCount = languageVersion < ScriptTarget.ES6 && hasDeclaredRestParameter(node) ? 1 : 0; emitList(parameters, skipCount, parameters.length - omitCount - skipCount, /*multiLine*/ false, /*trailingComma*/ false); } write(")"); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 31e4277f75f..2b21129618d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1500,23 +1500,26 @@ namespace ts { return isRestParameter(lastOrUndefined(s.parameters)); } - export function isRestParameter(node: ParameterDeclaration) { - if (node) { - if (node.flags & NodeFlags.JavaScriptFile) { - if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { - return true; - } + export function hasDeclaredRestParameter(s: SignatureDeclaration): boolean { + return isDeclaredRestParam(lastOrUndefined(s.parameters)); + } - const paramTag = getCorrespondingJSDocParameterTag(node); - if (paramTag && paramTag.typeExpression) { - return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; - } + export function isRestParameter(node: ParameterDeclaration) { + if (node && (node.flags & NodeFlags.JavaScriptFile)) { + if (node.type && node.type.kind === SyntaxKind.JSDocVariadicType) { + return true; } - return node.dotDotDotToken !== undefined; + const paramTag = getCorrespondingJSDocParameterTag(node); + if (paramTag && paramTag.typeExpression) { + return paramTag.typeExpression.type.kind === SyntaxKind.JSDocVariadicType; + } } + return isDeclaredRestParam(node); + } - return false; + export function isDeclaredRestParam(node: ParameterDeclaration) { + return node && node.dotDotDotToken !== undefined; } diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.js b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.js new file mode 100644 index 00000000000..e1675ff7131 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.js @@ -0,0 +1,51 @@ +//// [_apply.js] + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + var length = args.length; + switch (length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +export default apply; + +//// [apply.js] +define("_apply", ["require", "exports"], function (require, exports) { + "use strict"; + /** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ + function apply(func, thisArg, args) { + var length = args.length; + switch (length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); + } + exports.__esModule = true; + exports["default"] = apply; +}); diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.symbols b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.symbols new file mode 100644 index 00000000000..62e47c8a3c4 --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.symbols @@ -0,0 +1,68 @@ +=== tests/cases/compiler/_apply.js === + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { +>apply : Symbol(apply, Decl(_apply.js, 0, 0)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) + + var length = args.length; +>length : Symbol(length, Decl(_apply.js, 12, 7)) +>args.length : Symbol(Array.length, Decl(lib.d.ts, --, --)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) +>length : Symbol(Array.length, Decl(lib.d.ts, --, --)) + + switch (length) { +>length : Symbol(length, Decl(_apply.js, 12, 7)) + + case 0: return func.call(thisArg); +>func.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) + + case 1: return func.call(thisArg, args[0]); +>func.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) + + case 2: return func.call(thisArg, args[0], args[1]); +>func.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) + + case 3: return func.call(thisArg, args[0], args[1], args[2]); +>func.call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>call : Symbol(Function.call, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) + } + return func.apply(thisArg, args); +>func.apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>func : Symbol(func, Decl(_apply.js, 11, 15)) +>apply : Symbol(Function.apply, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>thisArg : Symbol(thisArg, Decl(_apply.js, 11, 20)) +>args : Symbol(args, Decl(_apply.js, 11, 29)) +} + +export default apply; +>apply : Symbol(apply, Decl(_apply.js, 0, 0)) + diff --git a/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types new file mode 100644 index 00000000000..78d0fd1392b --- /dev/null +++ b/tests/baselines/reference/jsFileCompilationRestParamJsDocFunction.types @@ -0,0 +1,89 @@ +=== tests/cases/compiler/_apply.js === + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { +>apply : (func: Function, thisArg: any, ...args: any[]) => any +>func : Function +>thisArg : any +>args : any[] + + var length = args.length; +>length : number +>args.length : number +>args : any[] +>length : number + + switch (length) { +>length : number + + case 0: return func.call(thisArg); +>0 : number +>func.call(thisArg) : any +>func.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>func : Function +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>thisArg : any + + case 1: return func.call(thisArg, args[0]); +>1 : number +>func.call(thisArg, args[0]) : any +>func.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>func : Function +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>thisArg : any +>args[0] : any +>args : any[] +>0 : number + + case 2: return func.call(thisArg, args[0], args[1]); +>2 : number +>func.call(thisArg, args[0], args[1]) : any +>func.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>func : Function +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>thisArg : any +>args[0] : any +>args : any[] +>0 : number +>args[1] : any +>args : any[] +>1 : number + + case 3: return func.call(thisArg, args[0], args[1], args[2]); +>3 : number +>func.call(thisArg, args[0], args[1], args[2]) : any +>func.call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>func : Function +>call : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, ...argArray: any[]): U; (this: Function, thisArg: any, ...argArray: any[]): any; } +>thisArg : any +>args[0] : any +>args : any[] +>0 : number +>args[1] : any +>args : any[] +>1 : number +>args[2] : any +>args : any[] +>2 : number + } + return func.apply(thisArg, args); +>func.apply(thisArg, args) : any +>func.apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>func : Function +>apply : { (this: (this: T, ...argArray: any[]) => U, thisArg: T, argArray?: any): U; (this: Function, thisArg: any, argArray?: any): any; } +>thisArg : any +>args : any[] +} + +export default apply; +>apply : (func: Function, thisArg: any, ...args: any[]) => any + diff --git a/tests/cases/compiler/jsFileCompilationRestParamJsDocFunction.ts b/tests/cases/compiler/jsFileCompilationRestParamJsDocFunction.ts new file mode 100644 index 00000000000..03ad2d1b2ff --- /dev/null +++ b/tests/cases/compiler/jsFileCompilationRestParamJsDocFunction.ts @@ -0,0 +1,27 @@ +// @allowJs: true +// @out: apply.js +// @module: amd + +// @filename: _apply.js +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + var length = args.length; + switch (length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +export default apply; \ No newline at end of file