Skip to content

Commit

Permalink
fix(@ngtools/webpack): support jit mode guarded class metadata removal
Browse files Browse the repository at this point in the history
This adds support for the alternate emit form of `ɵsetClassMetadata` that is guarded by `ngJitMode` instead of a pure annotation.
  • Loading branch information
clydin authored and alan-agius4 committed Oct 15, 2020
1 parent 9980f81 commit 31875e9
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 10 deletions.
Expand Up @@ -25,14 +25,30 @@ export function removeIvyJitSupportCalls(
return false;
}

let shouldRemove = false;

if (ngModuleScope && ts.isBinaryExpression(innerStatement.expression)) {
return isIvyPrivateCallExpression(innerStatement.expression.right, 'ɵɵsetNgModuleScope');
shouldRemove = isIvyPrivateCallExpression(
innerStatement.expression.right,
'ɵɵsetNgModuleScope',
);
}

if (classMetadata && !shouldRemove) {
if (ts.isBinaryExpression(innerStatement.expression)) {
shouldRemove = isIvyPrivateCallExpression(
innerStatement.expression.right,
'ɵsetClassMetadata',
);
} else {
shouldRemove = isIvyPrivateCallExpression(
innerStatement.expression,
'ɵsetClassMetadata',
);
}
}

return (
classMetadata &&
isIvyPrivateCallExpression(innerStatement.expression, 'ɵsetClassMetadata')
);
return shouldRemove;
})
.forEach(statement => ops.push(new RemoveNodeOperation(sourceFile, statement)));

Expand Down
Expand Up @@ -51,9 +51,39 @@ const input = tags.stripIndent`
}], null, null); })();
`;

const inputNoPure = tags.stripIndent`
export class AppModule {
}
AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] });
AppModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AppModule_Factory(t) { return new (t || AppModule)(); }, providers: [], imports: [[
BrowserModule,
AppRoutingModule
]] });
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AppModule, { declarations: [AppComponent,
ExampleComponent], imports: [BrowserModule,
AppRoutingModule] }); })();
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵsetClassMetadata(AppModule, [{
type: NgModule,
args: [{
declarations: [
AppComponent,
ExampleComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
}]
}], null, null); })();
`;

// tslint:disable-next-line: no-big-function
describe('@ngtools/webpack transformers', () => {
// tslint:disable-next-line: no-big-function
describe('remove-ivy-dev-calls', () => {
it('should allow removing only set class metadata', () => {
it('should allow removing only set class metadata with pure annotation', () => {
const output = tags.stripIndent`
export class AppModule {
}
Expand All @@ -74,7 +104,28 @@ describe('@ngtools/webpack transformers', () => {
expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing only ng module scope', () => {
it('should allow removing only set class metadata', () => {
const output = tags.stripIndent`
export class AppModule {
}
AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] });
AppModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AppModule_Factory(t) { return new (t || AppModule)(); }, providers: [], imports: [[
BrowserModule,
AppRoutingModule
]] });
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AppModule, { declarations: [AppComponent,
ExampleComponent], imports: [BrowserModule,
AppRoutingModule] }); })();
`;

const result = transform(inputNoPure, getTypeChecker =>
removeIvyJitSupportCalls(true, false, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing only ng module scope with pure annotation', () => {
const output = tags.stripIndent`
export class AppModule {
}
Expand Down Expand Up @@ -107,7 +158,40 @@ describe('@ngtools/webpack transformers', () => {
expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing both set class metadata and ng module scope', () => {
it('should allow removing only ng module scope', () => {
const output = tags.stripIndent`
export class AppModule {
}
AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] });
AppModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AppModule_Factory(t) { return new (t || AppModule)(); }, providers: [], imports: [[
BrowserModule,
AppRoutingModule
]] });
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵsetClassMetadata(AppModule, [{
type: NgModule,
args: [{
declarations: [
AppComponent,
ExampleComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
}]
}], null, null); })();
`;

const result = transform(inputNoPure, getTypeChecker =>
removeIvyJitSupportCalls(false, true, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing both set class metadata and ng module scope with pure annotation', () => {
const output = tags.stripIndent`
export class AppModule {
}
Expand All @@ -125,15 +209,41 @@ describe('@ngtools/webpack transformers', () => {
expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing neither set class metadata nor ng module scope', () => {
it('should allow removing both set class metadata and ng module scope', () => {
const output = tags.stripIndent`
export class AppModule {
}
AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] });
AppModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AppModule_Factory(t) { return new (t || AppModule)(); }, providers: [], imports: [[
BrowserModule,
AppRoutingModule
]] });
`;

const result = transform(inputNoPure, getTypeChecker =>
removeIvyJitSupportCalls(true, true, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should allow removing neither set class metadata nor ng module scope with pure annotation', () => {
const result = transform(input, getTypeChecker =>
removeIvyJitSupportCalls(false, false, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${input}`);
});

it('should strip unused imports when removing set class metadata and ng module scope', () => {
it('should allow removing neither set class metadata nor ng module scope', () => {
const result = transform(inputNoPure, getTypeChecker =>
removeIvyJitSupportCalls(false, false, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${inputNoPure}`);
});

it('should strip unused imports when removing set class metadata and ng module scope with pure annotation', () => {
const imports = tags.stripIndent`
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
Expand Down Expand Up @@ -164,5 +274,35 @@ describe('@ngtools/webpack transformers', () => {
expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});

it('should strip unused imports when removing set class metadata and ng module scope', () => {
const imports = tags.stripIndent`
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ExampleComponent } from './example/example.component';
import * as i0 from "@angular/core";
`;

const output = tags.stripIndent`
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import * as i0 from "@angular/core";
export class AppModule {
}
AppModule.ɵmod = i0.ɵɵdefineNgModule({ type: AppModule, bootstrap: [AppComponent] });
AppModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AppModule_Factory(t) { return new (t || AppModule)(); }, providers: [], imports: [[
BrowserModule,
AppRoutingModule
]] });
`;

const result = transform(imports + inputNoPure, getTypeChecker =>
removeIvyJitSupportCalls(true, true, getTypeChecker),
);

expect(tags.oneLine`${result}`).toEqual(tags.oneLine`${output}`);
});
});
});

0 comments on commit 31875e9

Please sign in to comment.