Skip to content

Commit

Permalink
source maps sanitization adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Feb 4, 2016
1 parent c168e3e commit 2a30444
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 32 deletions.
17 changes: 17 additions & 0 deletions lib/esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,25 @@
if (transpiler == load.metadata.loaderModule)
return load.source;

// convert the source map into an object for transpilation chaining
if (typeof load.metadata.sourceMap == 'string')
load.metadata.sourceMap = JSON.parse(load.metadata.sourceMap);

return Promise.resolve(transpiler.translate.call(loader, load))
.then(function(source) {
// sanitize sourceMap if an object not a JSON string
var sourceMap = load.metadata.sourceMap;
if (sourceMap && typeof sourceMap == 'object') {
var originalName = load.name.split('!')[0];

// force set the filename of the original file
sourceMap.file = originalName + '!transpiled';

// force set the sources list if only one source
if (!sourceMap.sources || sourceMap.sources.length <= 1)
sourceMap.sources = [originalName];
}

if (load.metadata.format == 'esm' && !loader.builder && detectRegisterFormat(source))
load.metadata.format = 'register';
return source;
Expand Down
24 changes: 17 additions & 7 deletions lib/global-eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,37 @@ var __exec;
// used to support leading #!/usr/bin/env in scripts as supported in Node
var hashBangRegEx = /^\#\!.*/;

function getSource(load) {
function getSource(load, sourceMapOffset) {
var lastLineIndex = load.source.lastIndexOf('\n');

// wrap ES formats with a System closure for System global encapsulation
var wrap = load.metadata.format == 'esm' || load.metadata.format == 'register' || load.metadata.bundle;

var sourceMap = load.metadata.sourceMap;
if (sourceMap) {
if (typeof sourceMap != 'object')
throw new TypeError('load.metadata.sourceMap must be set to an object.');

if (sourceMapOffset && sourceMap.mappings)
sourceMap.mappings = ';' + sourceMap.mappings;
}

sourceMap = JSON.stringify(sourceMap);

return (wrap ? '(function(System) {' : '') + (load.metadata.format == 'cjs' ? load.source.replace(hashBangRegEx, '') : load.source) + (wrap ? '\n})(System);' : '')
// adds the sourceURL comment if not already present
+ (load.source.substr(lastLineIndex, 15) != '\n//# sourceURL='
? '\n//# sourceURL=' + load.address + (load.metadata.sourceMap ? '!transpiled' : '') : '')
? '\n//# sourceURL=' + load.address + (sourceMap ? '!transpiled' : '') : '')
// add sourceMappingURL if load.metadata.sourceMap is set
+ (load.metadata.sourceMap && hasBtoa &&
'\n//# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(load.metadata.sourceMap))) || '')
+ (sourceMap && hasBtoa && '\n//# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(sourceMap))) || '');
}

function evalExec(load) {
if (load.metadata.integrity)
throw new TypeError('Subresource integrity checking is not supported in Web Workers or Chrome Extensions.');
try {
preExec(this, load);
new Function(getSource(load)).call(__global);
new Function(getSource(load, true)).call(__global);
postExec();
}
catch(e) {
Expand All @@ -80,7 +90,7 @@ var __exec;
head = document.head || document.body || document.documentElement;

var script = document.createElement('script');
script.text = getSource(load);
script.text = getSource(load, false);
var onerror = window.onerror;
var e;
window.onerror = function(_e) {
Expand Down Expand Up @@ -114,7 +124,7 @@ var __exec;
throw new TypeError('Subresource integrity checking is unavailable in Node.');
try {
preExec(this, load);
vm.runInThisContext(getSource(load));
vm.runInThisContext(getSource(load, false));
postExec();
}
catch(e) {
Expand Down
48 changes: 23 additions & 25 deletions lib/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,36 +177,34 @@

hook('translate', function(translate) {
return function(load) {

/*
* Source map sanitization for load.metadata.sourceMap
* Used to set browser and build-level source maps for
* translated sources in a general way.
*
* This isn't plugin-specific, but can't go anywhere else for now
* As it is post-translate
*/
var sourceMap = load.metadata.sourceMap;

// if an object not a JSON string do sanitizing
if (sourceMap && typeof sourceMap == 'object') {
var originalName = load.name.split('!')[0];

// force set the filename of the original file
sourceMap.file = originalName + '!transpiled';

// force set the sources list if only one source
if (!sourceMap.sources || sourceMap.sources.length == 1)
sourceMap.sources = [originalName];
load.metadata.sourceMap = JSON.stringify(sourceMap);
}

var loader = this;
if (load.metadata.loaderModule && load.metadata.loaderModule.translate && load.metadata.format != 'defined') {
return Promise.resolve(load.metadata.loaderModule.translate.call(loader, load)).then(function(result) {
// NB we should probably enforce a string output
var sourceMap = load.metadata.sourceMap;

// sanitize sourceMap if an object not a JSON string
if (sourceMap) {
if (typeof sourceMap != 'object')
throw new Error('load.metadata.sourceMap must be set to an object.');

var originalName = load.name.split('!')[0];

// force set the filename of the original file
sourceMap.file = originalName + '!transpiled';

// force set the sources list if only one source
if (!sourceMap.sources || sourceMap.sources.length <= 1)
sourceMap.sources = [originalName];
}

// if running on file:/// URLs, sourcesContent is necessary
// load.metadata.sourceMap.sourcesContent = [load.source];

if (typeof result == 'string')
load.source = result;
else
warn.call(this, 'Plugin ' + load.metadata.loader + ' should return the source in translate, instead of setting load.source directly. This support will be deprecated.');

return translate.call(loader, load);
});
}
Expand Down

0 comments on commit 2a30444

Please sign in to comment.