fix(core): detect synthesized constructors that have been downleveled using TS 4.2 (#41305)
TypeScript 4.2 has changed its emitted syntax for synthetic constructors when using `downlevelIteration`, which affects ES5 bundles that have been downleveled from ES2015 bundles. This is typically the case for UMD bundles in the APF spec, as they are generated by downleveling the ESM2015 bundle into ES5. The reflection capabilities in the runtime need to recognize this new form to correctly deal with synthesized constructors, as otherwise JIT compilation could generate invalid factory functions. Fixes #41298 PR Close #41305
This commit is contained in:
parent
8d3da56eda
commit
274dc15452
|
@ -34,15 +34,22 @@ import {GetterFn, MethodFn, SetterFn} from './types';
|
||||||
* var _this = _super.apply(this, arguments) || this;
|
* var _this = _super.apply(this, arguments) || this;
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2:
|
||||||
* ```
|
* ```
|
||||||
* function MyClass() {
|
* function MyClass() {
|
||||||
* var _this = _super.apply(this, __spread(arguments)) || this;
|
* var _this = _super.apply(this, __spread(arguments)) || this;
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
|
* or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2:
|
||||||
|
* ```
|
||||||
|
* function MyClass() {
|
||||||
|
* var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this;
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* More details can be found in: https://github.com/angular/angular/issues/38453.
|
* More details can be found in: https://github.com/angular/angular/issues/38453.
|
||||||
*/
|
*/
|
||||||
export const ES5_DELEGATE_CTOR =
|
export const ES5_DELEGATE_CTOR =
|
||||||
/^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|[^()]+\(arguments\))\)/;
|
/^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|(?:[^()]+\(\[\],)?[^()]+\(arguments\))\)/;
|
||||||
/** Regular expression that detects ES2015 classes which extend from other classes. */
|
/** Regular expression that detects ES2015 classes which extend from other classes. */
|
||||||
export const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
|
export const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,7 +27,7 @@ genrule(
|
||||||
$(execpath @npm//typescript/bin:tsc) $< --outDir $$es2015_out_dir --target ES2015 \
|
$(execpath @npm//typescript/bin:tsc) $< --outDir $$es2015_out_dir --target ES2015 \
|
||||||
--types --module umd
|
--types --module umd
|
||||||
$(execpath @npm//typescript/bin:tsc) --outFile $@ $$es2015_out_file --allowJs \
|
$(execpath @npm//typescript/bin:tsc) --outFile $@ $$es2015_out_file --allowJs \
|
||||||
--types --target ES5
|
--types --target ES5 --downlevelIteration
|
||||||
""",
|
""",
|
||||||
tools = ["@npm//typescript/bin:tsc"],
|
tools = ["@npm//typescript/bin:tsc"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -202,7 +202,8 @@ class TestObj {
|
||||||
});
|
});
|
||||||
|
|
||||||
// See: https://github.com/angular/angular/issues/38453
|
// See: https://github.com/angular/angular/issues/38453
|
||||||
it('should support ES2015 downleveled classes', () => {
|
it('should support ES2015 downleveled classes (workspace TypeScript version) (downlevelIteration=true)',
|
||||||
|
() => {
|
||||||
const {ChildNoCtor, ChildNoCtorPrivateProps, ChildWithCtor} =
|
const {ChildNoCtor, ChildNoCtorPrivateProps, ChildWithCtor} =
|
||||||
require('./es5_downleveled_inheritance_fixture');
|
require('./es5_downleveled_inheritance_fixture');
|
||||||
|
|
||||||
|
@ -211,6 +212,40 @@ class TestObj {
|
||||||
expect(isDelegateCtor(ChildWithCtor.toString())).toBe(false);
|
expect(isDelegateCtor(ChildWithCtor.toString())).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support ES2015 downleveled classes (<TS4.2) (downlevelIteration=true)', () => {
|
||||||
|
const ChildNoCtor = `function ChildNoCtor() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}`;
|
||||||
|
const ChildNoCtorPrivateProps = `function ChildNoCtorPrivateProps() {
|
||||||
|
var _this = _super.apply(this, __spread(arguments)) || this;
|
||||||
|
_this.x = 10;
|
||||||
|
return _this;
|
||||||
|
}`;
|
||||||
|
const ChildWithCtor = `function ChildWithCtor() {
|
||||||
|
return _super.call(this) || this;
|
||||||
|
}`;
|
||||||
|
expect(isDelegateCtor(ChildNoCtor)).toBe(true);
|
||||||
|
expect(isDelegateCtor(ChildNoCtorPrivateProps)).toBe(true);
|
||||||
|
expect(isDelegateCtor(ChildWithCtor)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support ES2015 downleveled classes (>=TS4.2) (downlevelIteration=true)', () => {
|
||||||
|
const ChildNoCtor = `function ChildNoCtor() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}`;
|
||||||
|
const ChildNoCtorPrivateProps = `function ChildNoCtorPrivateProps() {
|
||||||
|
var _this = _super.apply(this, __spreadArray([], __read(arguments))) || this;
|
||||||
|
_this.x = 10;
|
||||||
|
return _this;
|
||||||
|
}`;
|
||||||
|
const ChildWithCtor = `function ChildWithCtor() {
|
||||||
|
return _super.call(this) || this;
|
||||||
|
}`;
|
||||||
|
expect(isDelegateCtor(ChildNoCtor)).toBe(true);
|
||||||
|
expect(isDelegateCtor(ChildNoCtorPrivateProps)).toBe(true);
|
||||||
|
expect(isDelegateCtor(ChildWithCtor)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('should support ES2015 classes when minified', () => {
|
it('should support ES2015 classes when minified', () => {
|
||||||
// These classes are ES2015 in minified form
|
// These classes are ES2015 in minified form
|
||||||
const ChildNoCtorMinified = 'class ChildNoCtor extends Parent{}';
|
const ChildNoCtorMinified = 'class ChildNoCtor extends Parent{}';
|
||||||
|
|
Loading…
Reference in New Issue