Skip to content

Commit 10f882c

Browse files
clydinalan-agius4
authored andcommitted
refactor(@angular/cli): use Node.js CommonJS wrapping for schematic encapsulation
The schematics encapsulation process now uses a similar wrapping setup to Node.js itself. This removes some custom code and also provides a more comprehensive global object which should provide improved compatibility for third-party packages used within schematics.
1 parent 4ae35a2 commit 10f882c

File tree

1 file changed

+16
-31
lines changed

1 file changed

+16
-31
lines changed

packages/angular/cli/src/command-builder/utilities/schematic-engine-host.ts

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import { RuleFactory, SchematicsException, Tree } from '@angular-devkit/schemati
1010
import { FileSystemCollectionDesc, NodeModulesEngineHost } from '@angular-devkit/schematics/tools';
1111
import { readFileSync } from 'fs';
1212
import { parse as parseJson } from 'jsonc-parser';
13-
import { createRequire } from 'module';
13+
import { Module, createRequire } from 'module';
1414
import { dirname, resolve } from 'path';
15-
import { TextEncoder } from 'util';
1615
import { Script } from 'vm';
1716
import { assertIsError } from '../../utilities/error';
1817

@@ -204,38 +203,24 @@ function wrap(
204203

205204
// Setup a wrapper function to capture the module's exports
206205
const schematicCode = readFileSync(schematicFile, 'utf8');
207-
// `module` is required due to @angular/localize ng-add being in UMD format
208-
const headerCode = '(function() {\nvar exports = {};\nvar module = { exports };\n';
209-
const footerCode = exportName
210-
? `\nreturn module.exports['${exportName}'];});`
211-
: '\nreturn module.exports;});';
212-
213-
const script = new Script(headerCode + schematicCode + footerCode, {
206+
const script = new Script(Module.wrap(schematicCode), {
214207
filename: schematicFile,
215-
lineOffset: 3,
208+
lineOffset: 1,
216209
});
217-
218-
const context = {
219-
__dirname: schematicDirectory,
220-
__filename: schematicFile,
221-
Buffer,
222-
// TextEncoder is used by the compiler to generate i18n message IDs. See:
223-
// https://github.com/angular/angular/blob/main/packages/compiler/src/i18n/digest.ts#L17
224-
// It is referenced globally, because it may be run either on the browser or the server.
225-
// Usually Node exposes it globally, but in order for it to work, our custom context
226-
// has to expose it too. Issue context: https://github.com/angular/angular/issues/48940.
227-
TextEncoder,
228-
console,
229-
process,
230-
get global() {
231-
return this;
232-
},
233-
require: customRequire,
210+
const schematicModule = new Module(schematicFile);
211+
const moduleFactory = script.runInThisContext();
212+
213+
return () => {
214+
moduleFactory(
215+
schematicModule.exports,
216+
customRequire,
217+
schematicModule,
218+
schematicFile,
219+
schematicDirectory,
220+
);
221+
222+
return exportName ? schematicModule.exports[exportName] : schematicModule.exports;
234223
};
235-
236-
const exportsFactory = script.runInNewContext(context);
237-
238-
return exportsFactory;
239224
}
240225

241226
function loadBuiltinModule(id: string): unknown {

0 commit comments

Comments
 (0)