Skip to content

Commit 996a413

Browse files
kyliauKeen Yee Liau
authored andcommitted
fix: ngcc should not run in tsconfig.json directory
`ngcc` should be run in the directory where it is resolved to, not the directory where `tsconfig.json` is located. Fix #1039
1 parent a03f022 commit 996a413

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

scripts/test.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ set -ex -o pipefail
88
yarn
99
yarn ngcc
1010
)
11+
(
12+
cd integration/workspace
13+
yarn
14+
)
1115

1216
# Server unit tests
1317
yarn run test

server/src/ngcc.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {fork} from 'child_process';
10-
import * as path from 'path';
10+
import {dirname, resolve} from 'path';
1111

1212
function resolveNgccFrom(directory: string): string|null {
1313
try {
@@ -28,19 +28,25 @@ interface Progress {
2828
* run ngcc.
2929
*/
3030
export async function resolveAndRunNgcc(tsconfig: string, progress: Progress): Promise<void> {
31-
const directory = path.dirname(tsconfig);
31+
const directory = dirname(tsconfig);
3232
const ngcc = resolveNgccFrom(directory);
3333
if (!ngcc) {
3434
throw new Error(`Failed to resolve ngcc from ${directory}`);
3535
}
36+
const index = ngcc.lastIndexOf('node_modules');
37+
// By default, ngcc assumes the node_modules directory that it needs to process
38+
// is in the cwd. In our case, we should set cwd to the directory where ngcc
39+
// is resolved to, not the directory where tsconfig.json is located. See
40+
// https://github.com/angular/angular/blob/e23fd1f38205410e0ecb601ec73847cea2dea2a8/packages/compiler-cli/ngcc/src/command_line_options.ts#L18-L24
41+
const cwd = index > 0 ? ngcc.slice(0, index) : process.cwd();
3642
const childProcess = fork(
3743
ngcc,
3844
[
3945
'--tsconfig',
4046
tsconfig,
4147
],
4248
{
43-
cwd: directory,
49+
cwd: resolve(cwd),
4450
});
4551

4652
let stderr = '';

server/src/tests/ngcc_spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import * as child_process from 'child_process';
10+
import {EventEmitter} from 'events';
11+
import {join, resolve} from 'path';
12+
13+
import {resolveAndRunNgcc} from '../ngcc';
14+
15+
const PACKAGE_ROOT = resolve(__dirname, '../../..');
16+
const WORKSPACE_ROOT = join(PACKAGE_ROOT, 'integration', 'workspace');
17+
const PROJECT = join(WORKSPACE_ROOT, 'projects', 'demo');
18+
19+
describe('resolveAndRunNgcc', () => {
20+
it('runs ngcc from node_modules where ngcc is resolved to', async () => {
21+
const fakeChild = new EventEmitter();
22+
const spy = spyOn(child_process, 'fork').and.returnValue(fakeChild as any);
23+
// Note that tsconfig.json is in the project directory
24+
const tsconfig = join(PROJECT, 'tsconfig.json');
25+
const promise = resolveAndRunNgcc(tsconfig, {report() {}});
26+
fakeChild.emit('close', 0 /* exit code */);
27+
await expectAsync(promise).toBeResolved();
28+
expect(spy.calls.count()).toBe(1);
29+
// First arg is the ngcc binary, second arg is program arguments, third
30+
// arg is fork options.
31+
const {cwd} = spy.calls.argsFor(0)[2]!;
32+
// cwd for ngcc should be in the workspace directory
33+
expect(cwd).toBe(WORKSPACE_ROOT);
34+
});
35+
});

0 commit comments

Comments
 (0)