Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(terser): support .map files in directory inputs #1250

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions packages/terser/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,27 @@ function isDirectory(input) {
/**
* Replaces directory url with the outputFile name in the url option of source-map argument
*/
function directoryArgs(residualArgs, outputFile) {
function directoryArgs(residualArgs, inputFile, outputFile) {
const sourceMapIndex = residualArgs.indexOf('--source-map');
if (sourceMapIndex === -1) {
return residualArgs;
}

const sourceMapOptions = residualArgs[sourceMapIndex + 1].split(',');
const newSourceMapOptions = sourceMapOptions.map(
// set the correct sourcemap url for this output file
let sourceMapOptions = residualArgs[sourceMapIndex + 1].split(',').map(
o => o.startsWith('url=') ? `url='${path.basename(outputFile)}.map'` : o);

// if an input .map file exists then set the correct sourcemap content option
if (fs.existsSync(`${inputFile}.map`)) {
// even on Windows terser expects '/' path separators so we normalize these in the sourcemap
// content file path below
sourceMapOptions = sourceMapOptions.map(
o => o.startsWith('content=') ? `content='${inputFile.replace(/\\/g, '/')}.map'` : o);
}

return [
...residualArgs.slice(0, sourceMapIndex + 1),
newSourceMapOptions.join(','),
sourceMapOptions.join(','),
...residualArgs.slice(sourceMapIndex + 2),
];
}
Expand All @@ -59,8 +67,10 @@ function terserDirectory(input, output, residual, terserBinary) {

function exec([inputFile, outputFile]) {
active++;
let args =
[terserBinary, inputFile, '--output', outputFile, ...directoryArgs(residual, outputFile)];
let args = [
terserBinary, inputFile, '--output', outputFile,
...directoryArgs(residual, inputFile, outputFile)
];

spawn(process.execPath, args)
.then(
Expand Down
5 changes: 4 additions & 1 deletion packages/terser/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ load("@npm_bazel_jasmine//:index.from_src.bzl", "jasmine_node_test")
jasmine_node_test(
name = "test",
srcs = ["directory-args.spec.js"],
deps = ["@npm_bazel_terser//:index.js"],
deps = [
"@npm//tmp",
"@npm_bazel_terser//:index.js",
],
)
29 changes: 23 additions & 6 deletions packages/terser/test/directory-args.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
const {directoryArgs} = require('npm_bazel_terser/index')
const fs = require('fs');
const path = require('path');
const tmp = require('tmp');

describe('directoryArgs', () => {
it('return a new array ref', () => {
const args = ['--source-map', ''];
const args = ['--source-map', '', ''];
expect(directoryArgs(args, '')).not.toBe(args);
});

Expand All @@ -11,18 +14,32 @@ describe('directoryArgs', () => {
expect(directoryArgs(args)).toBe(args);
});

it('should replace the directory url with the file url', () => {
it('should set the correct file url and souremap content', () => {
const out = tmp.dirSync().name;
const input = path.join(out, 'file.js');
const output = '/test/file.js';
const args = [
'--ie8',
'--source-map',
`root='http://foo.com/src',url='some_wrong_name'`,
`root='http://foo.com/src',url='some_wrong_name',content=inline`,
'--keep-fnames',
];
const output = '/test/file.js';
expect(directoryArgs(args, output)).toEqual([
// if no corresponding map file exists then sourcemap content should
// be left as inline
expect(directoryArgs(args, input, output)).toEqual([
'--ie8',
'--source-map',
`root='http://foo.com/src',url='${path.basename(output)}.map',content=inline`,
'--keep-fnames',
]);
// if a corresponding map file exists then sourcemap content should be set
// to the map file
fs.writeFileSync(`${input}.map`, '');
expect(directoryArgs(args, input, output)).toEqual([
'--ie8',
'--source-map',
`root='http://foo.com/src',url='file.js.map'`,
`root='http://foo.com/src',url='${path.basename(output)}.map',content='${
input.replace(/\\/g, '/')}.map'`,
'--keep-fnames',
]);
});
Expand Down
3 changes: 1 addition & 2 deletions packages/terser/test/directory_input/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
load("@build_bazel_rules_nodejs//:tools/declare_directory.bzl", "declare_directory")
load("@npm_bazel_jasmine//:index.from_src.bzl", "jasmine_node_test")
load("@npm_bazel_terser//:index.from_src.bzl", "terser_minified")
load(":rule.bzl", "declare_directory")

# Check that filegroups work
declare_directory(
name = "dir",
srcs = glob(["input*.js"]),
Expand Down
25 changes: 25 additions & 0 deletions packages/terser/test/sourcemap/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@build_bazel_rules_nodejs//:tools/declare_directory.bzl", "declare_directory")
load("@npm_bazel_jasmine//:index.from_src.bzl", "jasmine_node_test")
load("@npm_bazel_terser//:index.from_src.bzl", "terser_minified")

Expand All @@ -24,3 +25,27 @@ jasmine_node_test(
":src1.min",
],
)

declare_directory(
name = "dir",
srcs = [
"src1.js",
"src1.js.map",
],
)

terser_minified(
name = "dir.min",
src = "dir",
)

jasmine_node_test(
name = "directory_test",
srcs = [
"directory_spec.js",
],
data = ["@npm//source-map"],
deps = [
":dir.min",
],
)
27 changes: 27 additions & 0 deletions packages/terser/test/sourcemap/directory_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const fs = require('fs');
const sm = require('source-map');
const path = require('path');
const {runfiles} = require('build_bazel_rules_nodejs/internal/linker');

describe('terser on a directory with map files', () => {
it('should produce an output for each input', () => {
const out = runfiles.resolvePackageRelative('dir.min');
expect(fs.existsSync(out + '/src1.js')).toBeTruthy();
});

it('should produce a sourcemap output', async () => {
const out = runfiles.resolvePackageRelative('dir.min');
const file = require.resolve(out + '/src1.js.map');
const rawSourceMap = JSON.parse(fs.readFileSync(file, 'utf-8'));
await sm.SourceMapConsumer.with(rawSourceMap, null, consumer => {
const pos = consumer.originalPositionFor(
// position of MyClass in terser_minified output src1.min.js
// depends on DEBUG flag
!process.env['DEBUG'] ? {line: 1, column: 18} : {line: 3, column: 5});
expect(pos.source).toBe('src1.ts');
expect(pos.line).toBe(2);
expect(pos.column).toBe(14);
expect(pos.name).toBe('MyClass');
});
});
});