Skip to content

Commit e9279bb

Browse files
clydinvikerman
authored andcommitted
fix(@angular-devkit/build-angular): update sourcemaps during localization
1 parent 895fa62 commit e9279bb

File tree

2 files changed

+72
-17
lines changed

2 files changed

+72
-17
lines changed

packages/angular_devkit/build_angular/src/browser/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,9 @@ export function buildWebpackBrowser(
473473
inlineActions.push({
474474
filename: path.basename(result.original.filename),
475475
code: fs.readFileSync(result.original.filename, 'utf8'),
476+
map:
477+
result.original.map &&
478+
fs.readFileSync(result.original.map.filename, 'utf8'),
476479
outputPath: baseOutputPath,
477480
es5: false,
478481
missingTranslation: options.i18nMissingTranslation,
@@ -483,6 +486,9 @@ export function buildWebpackBrowser(
483486
inlineActions.push({
484487
filename: path.basename(result.downlevel.filename),
485488
code: fs.readFileSync(result.downlevel.filename, 'utf8'),
489+
map:
490+
result.downlevel.map &&
491+
fs.readFileSync(result.downlevel.map.filename, 'utf8'),
486492
outputPath: baseOutputPath,
487493
es5: true,
488494
missingTranslation: options.i18nMissingTranslation,

packages/angular_devkit/build_angular/src/utils/process-bundle.ts

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as path from 'path';
1212
import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map';
1313
import { minify } from 'terser';
1414
import * as v8 from 'v8';
15+
import { SourceMapSource } from 'webpack-sources';
1516
import { I18nOptions } from './i18n-options';
1617
import { manglingDisabled } from './mangle-options';
1718

@@ -131,7 +132,7 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
131132
downlevelCode = transformResult.code;
132133

133134
if (manualSourceMaps && sourceMap && transformResult.map) {
134-
downlevelMap = await mergeSourcemaps(sourceMap, transformResult.map);
135+
downlevelMap = await mergeSourceMapsFast(sourceMap, transformResult.map);
135136
} else {
136137
// undefined is needed here to normalize the property type
137138
downlevelMap = transformResult.map || undefined;
@@ -196,7 +197,28 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
196197
return result;
197198
}
198199

199-
async function mergeSourcemaps(first: RawSourceMap, second: RawSourceMap) {
200+
function mergeSourceMaps(
201+
inputCode: string,
202+
inputSourceMap: RawSourceMap,
203+
resultCode: string,
204+
resultSourceMap: RawSourceMap,
205+
filename: string,
206+
): RawSourceMap {
207+
// More accurate but significantly more costly
208+
209+
// The last argument is not yet in the typings
210+
// tslint:disable-next-line: no-any
211+
return new (SourceMapSource as any)(
212+
resultCode,
213+
filename,
214+
resultSourceMap,
215+
inputCode,
216+
inputSourceMap,
217+
true,
218+
).map();
219+
}
220+
221+
async function mergeSourceMapsFast(first: RawSourceMap, second: RawSourceMap) {
200222
const sourceRoot = first.sourceRoot;
201223
const generator = new SourceMapGenerator();
202224

@@ -446,6 +468,7 @@ async function processRuntime(
446468
export interface InlineOptions {
447469
filename: string;
448470
code: string;
471+
map?: string;
449472
es5: boolean;
450473
outputPath: string;
451474
missingTranslation?: 'warning' | 'error' | 'ignore';
@@ -469,14 +492,7 @@ export async function inlineLocales(options: InlineOptions) {
469492
}
470493

471494
if (!options.code.includes(localizeName)) {
472-
for (const locale of i18n.inlineLocales) {
473-
fs.writeFileSync(
474-
path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename),
475-
options.code,
476-
);
477-
}
478-
479-
return { file: options.filename, diagnostics: [], count: 0 };
495+
return inlineCopyOnly(options);
480496
}
481497

482498
const { default: MagicString } = await import('magic-string');
@@ -490,7 +506,12 @@ export async function inlineLocales(options: InlineOptions) {
490506
const diagnostics = new localizeDiag.Diagnostics();
491507

492508
const positions = findLocalizePositions(options, utils);
509+
if (positions.length === 0) {
510+
return inlineCopyOnly(options);
511+
}
512+
493513
const content = new MagicString(options.code);
514+
const inputMap = options.map && JSON.parse(options.map) as RawSourceMap;
494515

495516
for (const locale of i18n.inlineLocales) {
496517
const isSourceLocale = locale === i18n.sourceLocale;
@@ -512,15 +533,46 @@ export async function inlineLocales(options: InlineOptions) {
512533
}
513534

514535
const output = content.toString();
515-
fs.writeFileSync(
516-
path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename),
517-
output,
536+
const outputPath = path.join(
537+
options.outputPath,
538+
i18n.flatOutput ? '' : locale,
539+
options.filename,
518540
);
541+
fs.writeFileSync(outputPath, output);
542+
543+
if (inputMap) {
544+
const contentMap = content.generateMap();
545+
const outputMap = mergeSourceMaps(
546+
options.code,
547+
inputMap,
548+
output,
549+
contentMap,
550+
options.filename,
551+
);
552+
553+
fs.writeFileSync(outputPath + '.map', JSON.stringify(outputMap));
554+
}
519555
}
520556

521557
return { file: options.filename, diagnostics: diagnostics.messages, count: positions.length };
522558
}
523559

560+
function inlineCopyOnly(options: InlineOptions) {
561+
if (!i18n) {
562+
throw new Error('i18n options are missing');
563+
}
564+
565+
for (const locale of i18n.inlineLocales) {
566+
const outputPath = path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename);
567+
fs.writeFileSync(outputPath, options.code);
568+
if (options.map) {
569+
fs.writeFileSync(outputPath + '.map', options.map);
570+
}
571+
}
572+
573+
return { file: options.filename, diagnostics: [], count: 0 };
574+
}
575+
524576
function findLocalizePositions(
525577
options: InlineOptions,
526578
utils: typeof import('@angular/localize/src/tools/src/translate/source_files/source_file_utils'),
@@ -536,10 +588,7 @@ function findLocalizePositions(
536588
traverse(ast, {
537589
CallExpression(path: NodePath<types.CallExpression>) {
538590
const callee = path.get('callee');
539-
if (
540-
callee.isIdentifier() &&
541-
callee.node.name === localizeName
542-
) {
591+
if (callee.isIdentifier() && callee.node.name === localizeName) {
543592
const messageParts = utils.unwrapMessagePartsFromLocalizeCall(path);
544593
const expressions = utils.unwrapSubstitutionsFromLocalizeCall(path.node);
545594
positions.push({

0 commit comments

Comments
 (0)