Skip to content

Commit 2fa59d5

Browse files
authored
Merge pull request #16120 from Microsoft/fix15857
Add wrapper to emit statics/decorators inside es5 class
2 parents 315b72d + 3ddbfca commit 2fa59d5

File tree

176 files changed

+1907
-1443
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

176 files changed

+1907
-1443
lines changed

src/compiler/core.ts

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -752,18 +752,34 @@ namespace ts {
752752
return to;
753753
}
754754

755+
/**
756+
* Gets the actual offset into an array for a relative offset. Negative offsets indicate a
757+
* position offset from the end of the array.
758+
*/
759+
function toOffset(array: any[], offset: number) {
760+
return offset < 0 ? array.length + offset : offset;
761+
}
762+
755763
/**
756764
* Appends a range of value to an array, returning the array.
757765
*
758766
* @param to The array to which `value` is to be appended. If `to` is `undefined`, a new array
759767
* is created if `value` was appended.
760768
* @param from The values to append to the array. If `from` is `undefined`, nothing is
761769
* appended. If an element of `from` is `undefined`, that element is not appended.
770+
* @param start The offset in `from` at which to start copying values.
771+
* @param end The offset in `from` at which to stop copying values (non-inclusive).
762772
*/
763-
export function addRange<T>(to: T[] | undefined, from: T[] | undefined): T[] | undefined {
773+
export function addRange<T>(to: T[] | undefined, from: T[] | undefined, start?: number, end?: number): T[] | undefined {
764774
if (from === undefined) return to;
765-
for (const v of from) {
766-
to = append(to, v);
775+
if (to === undefined) return from.slice(start, end);
776+
start = start === undefined ? 0 : toOffset(from, start);
777+
end = end === undefined ? from.length : toOffset(from, end);
778+
for (let i = start; i < end && i < from.length; i++) {
779+
const v = from[i];
780+
if (v !== undefined) {
781+
to.push(from[i]);
782+
}
767783
}
768784
return to;
769785
}
@@ -788,28 +804,38 @@ namespace ts {
788804
return true;
789805
}
790806

807+
/**
808+
* Returns the element at a specific offset in an array if non-empty, `undefined` otherwise.
809+
* A negative offset indicates the element should be retrieved from the end of the array.
810+
*/
811+
export function elementAt<T>(array: T[] | undefined, offset: number): T | undefined {
812+
if (array) {
813+
offset = toOffset(array, offset);
814+
if (offset < array.length) {
815+
return array[offset];
816+
}
817+
}
818+
return undefined;
819+
}
820+
791821
/**
792822
* Returns the first element of an array if non-empty, `undefined` otherwise.
793823
*/
794-
export function firstOrUndefined<T>(array: T[]): T {
795-
return array && array.length > 0
796-
? array[0]
797-
: undefined;
824+
export function firstOrUndefined<T>(array: T[]): T | undefined {
825+
return elementAt(array, 0);
798826
}
799827

800828
/**
801829
* Returns the last element of an array if non-empty, `undefined` otherwise.
802830
*/
803-
export function lastOrUndefined<T>(array: T[]): T {
804-
return array && array.length > 0
805-
? array[array.length - 1]
806-
: undefined;
831+
export function lastOrUndefined<T>(array: T[]): T | undefined {
832+
return elementAt(array, -1);
807833
}
808834

809835
/**
810836
* Returns the only element of an array if it contains only one element, `undefined` otherwise.
811837
*/
812-
export function singleOrUndefined<T>(array: T[]): T {
838+
export function singleOrUndefined<T>(array: T[]): T | undefined {
813839
return array && array.length === 1
814840
? array[0]
815841
: undefined;
@@ -1137,6 +1163,15 @@ namespace ts {
11371163
return Array.isArray ? Array.isArray(value) : value instanceof Array;
11381164
}
11391165

1166+
export function tryCast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut | undefined {
1167+
return value !== undefined && test(value) ? value : undefined;
1168+
}
1169+
1170+
export function cast<TOut extends TIn, TIn = any>(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut {
1171+
if (value !== undefined && test(value)) return value;
1172+
Debug.fail(`Invalid cast. The supplied value did not pass the test '${Debug.getFunctionName(test)}'.`);
1173+
}
1174+
11401175
/** Does nothing. */
11411176
export function noop(): void {}
11421177

@@ -2222,8 +2257,11 @@ namespace ts {
22222257
this.declarations = undefined;
22232258
}
22242259

2225-
function Type(this: Type, _checker: TypeChecker, flags: TypeFlags) {
2260+
function Type(this: Type, checker: TypeChecker, flags: TypeFlags) {
22262261
this.flags = flags;
2262+
if (Debug.isDebugging) {
2263+
this.checker = checker;
2264+
}
22272265
}
22282266

22292267
function Signature() {
@@ -2260,24 +2298,42 @@ namespace ts {
22602298

22612299
export namespace Debug {
22622300
export let currentAssertionLevel = AssertionLevel.None;
2301+
export let isDebugging = false;
22632302

22642303
export function shouldAssert(level: AssertionLevel): boolean {
22652304
return currentAssertionLevel >= level;
22662305
}
22672306

2268-
export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string): void {
2307+
export function assert(expression: boolean, message?: string, verboseDebugInfo?: () => string, stackCrawlMark?: Function): void {
22692308
if (!expression) {
2270-
let verboseDebugString = "";
22712309
if (verboseDebugInfo) {
2272-
verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo();
2310+
message += "\r\nVerbose Debug Information: " + verboseDebugInfo();
22732311
}
2274-
debugger;
2275-
throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString);
2312+
fail(message ? "False expression: " + message : "False expression.", stackCrawlMark || assert);
2313+
}
2314+
}
2315+
2316+
export function fail(message?: string, stackCrawlMark?: Function): void {
2317+
debugger;
2318+
const e = new Error(message ? `Debug Failure. ` : "Debug Failure.");
2319+
if ((<any>Error).captureStackTrace) {
2320+
(<any>Error).captureStackTrace(e, stackCrawlMark || fail);
22762321
}
2322+
throw e;
22772323
}
22782324

2279-
export function fail(message?: string): void {
2280-
Debug.assert(/*expression*/ false, message);
2325+
export function getFunctionName(func: Function) {
2326+
if (typeof func !== "function") {
2327+
return "";
2328+
}
2329+
else if (func.hasOwnProperty("name")) {
2330+
return (<any>func).name;
2331+
}
2332+
else {
2333+
const text = Function.prototype.toString.call(func);
2334+
const match = /^function\s+([\w\$]+)\s*\(/.exec(text);
2335+
return match ? match[1] : "";
2336+
}
22812337
}
22822338
}
22832339

@@ -2443,4 +2499,4 @@ namespace ts {
24432499
export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
24442500
return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs;
24452501
}
2446-
}
2502+
}

src/compiler/factory.ts

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,6 +2134,24 @@ namespace ts {
21342134

21352135
// Compound nodes
21362136

2137+
export function createImmediatelyInvokedFunctionExpression(statements: Statement[]): CallExpression;
2138+
export function createImmediatelyInvokedFunctionExpression(statements: Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
2139+
export function createImmediatelyInvokedFunctionExpression(statements: Statement[], param?: ParameterDeclaration, paramValue?: Expression) {
2140+
return createCall(
2141+
createFunctionExpression(
2142+
/*modifiers*/ undefined,
2143+
/*asteriskToken*/ undefined,
2144+
/*name*/ undefined,
2145+
/*typeParameters*/ undefined,
2146+
/*parameters*/ param ? [param] : [],
2147+
/*type*/ undefined,
2148+
createBlock(statements, /*multiLine*/ true)
2149+
),
2150+
/*typeArguments*/ undefined,
2151+
/*argumentsArray*/ paramValue ? [paramValue] : []
2152+
);
2153+
}
2154+
21372155
export function createComma(left: Expression, right: Expression) {
21382156
return <Expression>createBinary(left, SyntaxKind.CommaToken, right);
21392157
}
@@ -3216,6 +3234,26 @@ namespace ts {
32163234
return isBlock(node) ? node : setTextRange(createBlock([setTextRange(createReturn(node), node)], multiLine), node);
32173235
}
32183236

3237+
export function convertFunctionDeclarationToExpression(node: FunctionDeclaration) {
3238+
Debug.assert(!!node.body);
3239+
const updated = createFunctionExpression(
3240+
node.modifiers,
3241+
node.asteriskToken,
3242+
node.name,
3243+
node.typeParameters,
3244+
node.parameters,
3245+
node.type,
3246+
node.body
3247+
);
3248+
setOriginalNode(updated, node);
3249+
setTextRange(updated, node);
3250+
if (node.startsOnNewLine) {
3251+
updated.startsOnNewLine = true;
3252+
}
3253+
aggregateTransformFlags(updated);
3254+
return updated;
3255+
}
3256+
32193257
function isUseStrictPrologue(node: ExpressionStatement): boolean {
32203258
return (node.expression as StringLiteral).text === "use strict";
32213259
}
@@ -3614,7 +3652,7 @@ namespace ts {
36143652
if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) {
36153653
const mutableCall = getMutableClone(emittedExpression);
36163654
mutableCall.expression = setTextRange(createParen(callee), callee);
3617-
return recreatePartiallyEmittedExpressions(expression, mutableCall);
3655+
return recreateOuterExpressions(expression, mutableCall, OuterExpressionKinds.PartiallyEmittedExpressions);
36183656
}
36193657
}
36203658
else {
@@ -3656,22 +3694,6 @@ namespace ts {
36563694
}
36573695
}
36583696

3659-
/**
3660-
* Clones a series of not-emitted expressions with a new inner expression.
3661-
*
3662-
* @param originalOuterExpression The original outer expression.
3663-
* @param newInnerExpression The new inner expression.
3664-
*/
3665-
function recreatePartiallyEmittedExpressions(originalOuterExpression: Expression, newInnerExpression: Expression) {
3666-
if (isPartiallyEmittedExpression(originalOuterExpression)) {
3667-
const clone = getMutableClone(originalOuterExpression);
3668-
clone.expression = recreatePartiallyEmittedExpressions(clone.expression, newInnerExpression);
3669-
return clone;
3670-
}
3671-
3672-
return newInnerExpression;
3673-
}
3674-
36753697
function getLeftmostExpression(node: Expression): Expression {
36763698
while (true) {
36773699
switch (node.kind) {
@@ -3718,6 +3740,22 @@ namespace ts {
37183740
All = Parentheses | Assertions | PartiallyEmittedExpressions
37193741
}
37203742

3743+
export type OuterExpression = ParenthesizedExpression | TypeAssertion | AsExpression | NonNullExpression | PartiallyEmittedExpression;
3744+
3745+
export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression {
3746+
switch (node.kind) {
3747+
case SyntaxKind.ParenthesizedExpression:
3748+
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
3749+
case SyntaxKind.TypeAssertionExpression:
3750+
case SyntaxKind.AsExpression:
3751+
case SyntaxKind.NonNullExpression:
3752+
return (kinds & OuterExpressionKinds.Assertions) !== 0;
3753+
case SyntaxKind.PartiallyEmittedExpression:
3754+
return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0;
3755+
}
3756+
return false;
3757+
}
3758+
37213759
export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression;
37223760
export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node;
37233761
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) {
@@ -3754,8 +3792,8 @@ namespace ts {
37543792
export function skipAssertions(node: Expression): Expression;
37553793
export function skipAssertions(node: Node): Node;
37563794
export function skipAssertions(node: Node): Node {
3757-
while (isAssertionExpression(node)) {
3758-
node = (<AssertionExpression>node).expression;
3795+
while (isAssertionExpression(node) || node.kind === SyntaxKind.NonNullExpression) {
3796+
node = (<AssertionExpression | NonNullExpression>node).expression;
37593797
}
37603798

37613799
return node;
@@ -3771,6 +3809,26 @@ namespace ts {
37713809
return node;
37723810
}
37733811

3812+
function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) {
3813+
switch (outerExpression.kind) {
3814+
case SyntaxKind.ParenthesizedExpression: return updateParen(outerExpression, expression);
3815+
case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression);
3816+
case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type);
3817+
case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression);
3818+
case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression);
3819+
}
3820+
}
3821+
3822+
export function recreateOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression {
3823+
if (outerExpression && isOuterExpression(outerExpression, kinds)) {
3824+
return updateOuterExpression(
3825+
outerExpression,
3826+
recreateOuterExpressions(outerExpression.expression, innerExpression)
3827+
);
3828+
}
3829+
return innerExpression;
3830+
}
3831+
37743832
export function startOnNewLine<T extends Node>(node: T): T {
37753833
node.startsOnNewLine = true;
37763834
return node;

src/compiler/sys.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ namespace ts {
4141
realpath?(path: string): string;
4242
/*@internal*/ getEnvironmentVariable(name: string): string;
4343
/*@internal*/ tryEnableSourceMapsForHost?(): void;
44+
/*@internal*/ debugMode?: boolean;
4445
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
4546
clearTimeout?(timeoutId: any): void;
4647
}
@@ -428,6 +429,7 @@ namespace ts {
428429
realpath(path: string): string {
429430
return _fs.realpathSync(path);
430431
},
432+
debugMode: some(<string[]>process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)),
431433
tryEnableSourceMapsForHost() {
432434
try {
433435
require("source-map-support").install();
@@ -517,4 +519,7 @@ namespace ts {
517519
? AssertionLevel.Normal
518520
: AssertionLevel.None;
519521
}
522+
if (sys && sys.debugMode) {
523+
Debug.isDebugging = true;
524+
}
520525
}

0 commit comments

Comments
 (0)