mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Prefer source-maps in memory in a parsed JSON form
This commit is contained in:
@@ -84,8 +84,6 @@ var stripExportedVars = function (source, exports) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var addSharedHeader = function (source, sourceMap) {
|
var addSharedHeader = function (source, sourceMap) {
|
||||||
var sourceMapJSON = JSON.parse(sourceMap);
|
|
||||||
|
|
||||||
// We want the symbol "share" to be visible to all CoffeeScript files in the
|
// We want the symbol "share" to be visible to all CoffeeScript files in the
|
||||||
// package (and shared between them), but not visible to JavaScript
|
// package (and shared between them), but not visible to JavaScript
|
||||||
// files. (That's because we don't want to introduce two competing ways to
|
// files. (That's because we don't want to introduce two competing ways to
|
||||||
@@ -114,13 +112,13 @@ var addSharedHeader = function (source, sourceMap) {
|
|||||||
// There's no use strict, so we can just add the header at the very
|
// There's no use strict, so we can just add the header at the very
|
||||||
// beginning. This adds a line to the file, so we update the source map to
|
// beginning. This adds a line to the file, so we update the source map to
|
||||||
// add a single un-annotated line to the beginning.
|
// add a single un-annotated line to the beginning.
|
||||||
sourceMapJSON.mappings = ";" + sourceMapJSON.mappings;
|
sourceMap.mappings = ";" + sourceMap.mappings;
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
source: source,
|
source: source,
|
||||||
sourceMap: JSON.stringify(sourceMapJSON)
|
sourceMap: sourceMap
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +132,7 @@ var CoffeeCompiler = function () {
|
|||||||
max: CACHE_SIZE,
|
max: CACHE_SIZE,
|
||||||
// Cache is measured in bytes.
|
// Cache is measured in bytes.
|
||||||
length: function (value) {
|
length: function (value) {
|
||||||
return value.source.length + value.sourceMap.length;
|
return value.source.length + sourceMapLength(value.sourceMap);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self._diskCache = null;
|
self._diskCache = null;
|
||||||
@@ -188,6 +186,7 @@ _.extend(CoffeeCompiler.prototype, {
|
|||||||
var stripped = stripExportedVars(
|
var stripped = stripExportedVars(
|
||||||
output.js,
|
output.js,
|
||||||
_.pluck(inputFile.getDeclaredExports(), 'name'));
|
_.pluck(inputFile.getDeclaredExports(), 'name'));
|
||||||
|
console.log('>>>> ', typeof output.sourceMap, typeof output.v3SourceMap);
|
||||||
sourceWithMap = addSharedHeader(stripped, output.v3SourceMap);
|
sourceWithMap = addSharedHeader(stripped, output.v3SourceMap);
|
||||||
self._cache.set(cacheKey, sourceWithMap);
|
self._cache.set(cacheKey, sourceWithMap);
|
||||||
}
|
}
|
||||||
@@ -257,3 +256,12 @@ Plugin.registerCompiler({
|
|||||||
return new CoffeeCompiler();
|
return new CoffeeCompiler();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sourceMapLength(sm) {
|
||||||
|
if (! sm) return 0;
|
||||||
|
// sum the length of sources and the mappings, the size of
|
||||||
|
// metadata is ignored, but it is not a big deal
|
||||||
|
return sm.mappings.length
|
||||||
|
+ (sm.sourcesContent || []).reduce(function (soFar, current) {
|
||||||
|
return soFar + (current ? current.length : 0);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ var LessCompiler = function () {
|
|||||||
max: CACHE_SIZE,
|
max: CACHE_SIZE,
|
||||||
// Cache is measured in bytes (not counting the hashes).
|
// Cache is measured in bytes (not counting the hashes).
|
||||||
length: function (value) {
|
length: function (value) {
|
||||||
return value.css.length + value.sourceMap.length;
|
return value.css.length + sourceMapLength(value.sourceMap);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self._diskCache = null;
|
self._diskCache = null;
|
||||||
@@ -100,7 +100,7 @@ _.extend(LessCompiler.prototype, {
|
|||||||
if (output.map) {
|
if (output.map) {
|
||||||
var map = JSON.parse(output.map);
|
var map = JSON.parse(output.map);
|
||||||
map.sources = map.sources.map(decodeFilePath);
|
map.sources = map.sources.map(decodeFilePath);
|
||||||
output.map = JSON.stringify(map);
|
output.map = map;
|
||||||
}
|
}
|
||||||
cacheEntry = {
|
cacheEntry = {
|
||||||
hashes: {},
|
hashes: {},
|
||||||
@@ -244,3 +244,12 @@ _.extend(MeteorImportLessFileManager.prototype, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sourceMapLength(sm) {
|
||||||
|
if (! sm) return 0;
|
||||||
|
// sum the length of sources and the mappings, the size of
|
||||||
|
// metadata is ignored, but it is not a big deal
|
||||||
|
return sm.mappings.length
|
||||||
|
+ (sm.sourcesContent || []).reduce(function (soFar, current) {
|
||||||
|
return soFar + (current ? current.length : 0);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ function StylusCompiler () {
|
|||||||
max: CACHE_SIZE,
|
max: CACHE_SIZE,
|
||||||
// Cache is measured in bytes (not counting the hashes).
|
// Cache is measured in bytes (not counting the hashes).
|
||||||
length: function (value) {
|
length: function (value) {
|
||||||
return value.css.length + value.sourceMap.length;
|
return value.css.length + sourceMapLength(value.sourceMap);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ StylusCompiler.prototype.processFilesForTarget = function (files) {
|
|||||||
cacheEntry = {
|
cacheEntry = {
|
||||||
hashes: {},
|
hashes: {},
|
||||||
css: css,
|
css: css,
|
||||||
sourceMap: JSON.stringify(sourcemap)
|
sourceMap: sourcemap
|
||||||
};
|
};
|
||||||
cacheEntry.hashes[absolutePath] = inputFile.getSourceHash();
|
cacheEntry.hashes[absolutePath] = inputFile.getSourceHash();
|
||||||
currentlyProcessedImports.forEach(function (path) {
|
currentlyProcessedImports.forEach(function (path) {
|
||||||
@@ -190,3 +190,12 @@ StylusCompiler.prototype._writeCache = function () {
|
|||||||
// XXX BBP no on-disk caching yet
|
// XXX BBP no on-disk caching yet
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function sourceMapLength(sm) {
|
||||||
|
if (! sm) return 0;
|
||||||
|
// sum the length of sources and the mappings, the size of
|
||||||
|
// metadata is ignored, but it is not a big deal
|
||||||
|
return sm.mappings.length
|
||||||
|
+ (sm.sourcesContent || []).reduce(function (soFar, current) {
|
||||||
|
return soFar + (current ? current.length : 0);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|||||||
@@ -235,7 +235,8 @@ var NodeModulesDirectory = function (options) {
|
|||||||
// - sourcePath: path to file on disk that will provide our contents
|
// - sourcePath: path to file on disk that will provide our contents
|
||||||
// - data: contents of the file as a Buffer
|
// - data: contents of the file as a Buffer
|
||||||
// - hash: optional, sha1 hash of the file contents, if known
|
// - hash: optional, sha1 hash of the file contents, if known
|
||||||
// - sourceMap: if 'data' is given, can be given instead of sourcePath. a string
|
// - sourceMap: if 'data' is given, can be given instead of
|
||||||
|
// sourcePath. a string or a JS Object. Will be stored as Object.
|
||||||
// - cacheable
|
// - cacheable
|
||||||
var File = function (options) {
|
var File = function (options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
@@ -390,8 +391,14 @@ _.extend(File.prototype, {
|
|||||||
setSourceMap: function (sourceMap, root) {
|
setSourceMap: function (sourceMap, root) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (typeof sourceMap !== "string")
|
if (sourceMap === null || ['object', 'string'].indexOf(typeof sourceMap) === -1) {
|
||||||
throw new Error("sourceMap must be given as a string");
|
throw new Error("sourceMap must be given as a string or an object");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof sourceMap === 'string') {
|
||||||
|
sourceMap = JSON.parse(sourceMap);
|
||||||
|
}
|
||||||
|
|
||||||
self.sourceMap = sourceMap;
|
self.sourceMap = sourceMap;
|
||||||
self.sourceMapRoot = root;
|
self.sourceMapRoot = root;
|
||||||
},
|
},
|
||||||
@@ -863,18 +870,20 @@ _.extend(Target.prototype, {
|
|||||||
// For every source file we process, sets the domain name to
|
// For every source file we process, sets the domain name to
|
||||||
// 'meteor://[emoji]app/', so there is a separate category in Chrome DevTools
|
// 'meteor://[emoji]app/', so there is a separate category in Chrome DevTools
|
||||||
// with the original sources.
|
// with the original sources.
|
||||||
rewriteSourceMaps: function () {
|
rewriteSourceMaps: Profile("Target#rewriteSourceMaps", function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
function rewriteSourceMap (sm) {
|
function rewriteSourceMap (sm) {
|
||||||
var smPlain = JSON.parse(sm);
|
sm.sources = sm.sources.map(function (path) {
|
||||||
smPlain.sources = smPlain.sources.map(function (path) {
|
const prefix = 'meteor://\u{1f4bb}app';
|
||||||
|
|
||||||
|
if (path.slice(0, prefix.length) === prefix) return path;
|
||||||
// This emoji makes sure the category is always last. The character
|
// This emoji makes sure the category is always last. The character
|
||||||
// is PERSONAL COMPUTER (yay ES6 unicode escapes):
|
// is PERSONAL COMPUTER (yay ES6 unicode escapes):
|
||||||
// http://www.fileformat.info/info/unicode/char/1f4bb/index.htm
|
// http://www.fileformat.info/info/unicode/char/1f4bb/index.htm
|
||||||
return 'meteor://\u{1f4bb}app' + (path[0] === '/' ? '' : '/') + path;
|
return prefix + (path[0] === '/' ? '' : '/') + path;
|
||||||
});
|
});
|
||||||
return JSON.stringify(smPlain);
|
return sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.js) {
|
if (self.js) {
|
||||||
@@ -890,7 +899,7 @@ _.extend(Target.prototype, {
|
|||||||
css.sourceMap = rewriteSourceMap(css.sourceMap);
|
css.sourceMap = rewriteSourceMap(css.sourceMap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
|
|
||||||
// Add a Cordova plugin dependency to the target. If the same plugin
|
// Add a Cordova plugin dependency to the target. If the same plugin
|
||||||
// has already been added at a different version and `override` is
|
// has already been added at a different version and `override` is
|
||||||
@@ -1072,13 +1081,13 @@ _.extend(ClientTarget.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (file.sourceMap) {
|
if (file.sourceMap) {
|
||||||
let mapData = file.sourceMap;
|
let mapData = null;
|
||||||
|
|
||||||
// don't need to do this in devel mode
|
// don't need to do this in devel mode
|
||||||
if (mode === 'production') {
|
if (mode === 'production') {
|
||||||
mapData = antiXSSIPrepend(file.sourceMap);
|
mapData = antiXSSIPrepend(JSON.stringify(file.sourceMap));
|
||||||
} else {
|
} else {
|
||||||
mapData = new Buffer(file.sourceMap, 'utf8');
|
mapData = new Buffer(JSON.stringify(file.sourceMap), 'utf8');
|
||||||
}
|
}
|
||||||
|
|
||||||
manifestItem.sourceMap = builder.writeToGeneratedFilename(
|
manifestItem.sourceMap = builder.writeToGeneratedFilename(
|
||||||
@@ -1390,7 +1399,7 @@ _.extend(JsImage.prototype, {
|
|||||||
// Write the source map.
|
// Write the source map.
|
||||||
loadItem.sourceMap = builder.writeToGeneratedFilename(
|
loadItem.sourceMap = builder.writeToGeneratedFilename(
|
||||||
sourceMapBaseName,
|
sourceMapBaseName,
|
||||||
{ data: new Buffer(item.sourceMap, 'utf8') }
|
{ data: new Buffer(JSON.stringify(item.sourceMap), 'utf8') }
|
||||||
);
|
);
|
||||||
|
|
||||||
var sourceMapFileName = files.pathBasename(loadItem.sourceMap);
|
var sourceMapFileName = files.pathBasename(loadItem.sourceMap);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ var _ = require('underscore');
|
|||||||
var Profile = require('./profile.js').Profile;
|
var Profile = require('./profile.js').Profile;
|
||||||
import {sha1} from './watch.js';
|
import {sha1} from './watch.js';
|
||||||
import LRU from 'lru-cache';
|
import LRU from 'lru-cache';
|
||||||
|
import {sourceMapLength} from './utils.js';
|
||||||
|
|
||||||
const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100;
|
const CACHE_SIZE = process.env.METEOR_LINKER_CACHE_SIZE || 1024*1024*100;
|
||||||
const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG;
|
const CACHE_DEBUG = !! process.env.METEOR_TEST_PRINT_LINKER_CACHE_DEBUG;
|
||||||
@@ -22,8 +23,7 @@ const LINKER_CACHE = new LRU({
|
|||||||
// Key is JSONification of all options plus all hashes.
|
// Key is JSONification of all options plus all hashes.
|
||||||
length: function (files) {
|
length: function (files) {
|
||||||
return files.reduce((soFar, current) => {
|
return files.reduce((soFar, current) => {
|
||||||
return soFar + current.data.length +
|
return soFar + current.data.length + sourceMapLength(current.sourceMap);
|
||||||
(current.sourceMap ? current.sourceMap.length : 0);
|
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -175,14 +175,19 @@ _.extend(InputFile.prototype, {
|
|||||||
* be satisfied if there are path conflicts.
|
* be satisfied if there are path conflicts.
|
||||||
* @param {String} options.data The content of the stylesheet that should be
|
* @param {String} options.data The content of the stylesheet that should be
|
||||||
* added.
|
* added.
|
||||||
* @param {String} options.sourceMap A stringified JSON sourcemap, in case the
|
* @param {String|Object} options.sourceMap A stringified JSON
|
||||||
* stylesheet was generated from a different file.
|
* sourcemap, in case the stylesheet was generated from a different
|
||||||
|
* file.
|
||||||
* @memberOf InputFile
|
* @memberOf InputFile
|
||||||
* @instance
|
* @instance
|
||||||
*/
|
*/
|
||||||
addStylesheet: function (options) {
|
addStylesheet: function (options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
// XXX BBP validate input!!
|
// XXX BBP validate input!!
|
||||||
|
if (options.sourceMap && typeof options.sourceMap === 'string') {
|
||||||
|
// XXX remove an anti-XSSI header? ")]}'\n"
|
||||||
|
options.sourceMap = JSON.parse(options.sourceMap);
|
||||||
|
}
|
||||||
self._resourceSlot.addStylesheet(options);
|
self._resourceSlot.addStylesheet(options);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -195,13 +200,18 @@ _.extend(InputFile.prototype, {
|
|||||||
* @param {String} options.path The path at which the JavaScript file
|
* @param {String} options.path The path at which the JavaScript file
|
||||||
* should be inserted, may not be honored in case of path conflicts.
|
* should be inserted, may not be honored in case of path conflicts.
|
||||||
* @param {String} options.data The code to be added.
|
* @param {String} options.data The code to be added.
|
||||||
* @param {String} options.sourceMap A stringified JSON sourcemap, in case the
|
* @param {String|Object} options.sourceMap A stringified JSON
|
||||||
* JavaScript file was generated from a different file.
|
* sourcemap, in case the JavaScript file was generated from a
|
||||||
|
* different file.
|
||||||
* @memberOf InputFile
|
* @memberOf InputFile
|
||||||
* @instance
|
* @instance
|
||||||
*/
|
*/
|
||||||
addJavaScript: function (options) {
|
addJavaScript: function (options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
if (options.sourceMap && typeof options.sourceMap === 'string') {
|
||||||
|
// XXX remove an anti-XSSI header? ")]}'\n"
|
||||||
|
options.sourceMap = JSON.parse(options.sourceMap);
|
||||||
|
}
|
||||||
self._resourceSlot.addJavaScript(options);
|
self._resourceSlot.addJavaScript(options);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -578,11 +588,13 @@ _.extend(PackageSourceBatch.prototype, {
|
|||||||
|
|
||||||
// Add each output as a resource
|
// Add each output as a resource
|
||||||
const ret = linkedFiles.map((file) => {
|
const ret = linkedFiles.map((file) => {
|
||||||
|
const sm = (typeof file.sourceMap === 'string')
|
||||||
|
? JSON.parse(file.sourceMap) : file.sourceMap;
|
||||||
return {
|
return {
|
||||||
type: "js",
|
type: "js",
|
||||||
data: new Buffer(file.source, 'utf8'), // XXX encoding
|
data: new Buffer(file.source, 'utf8'), // XXX encoding
|
||||||
servePath: file.servePath,
|
servePath: file.servePath,
|
||||||
sourceMap: file.sourceMap
|
sourceMap: sm
|
||||||
// XXX BBP hash? needed for minifiers?
|
// XXX BBP hash? needed for minifiers?
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ var isopackets = require('./isopackets.js');
|
|||||||
var watch = require('./watch.js');
|
var watch = require('./watch.js');
|
||||||
var Profile = require('./profile.js').Profile;
|
var Profile = require('./profile.js').Profile;
|
||||||
import LRU from 'lru-cache';
|
import LRU from 'lru-cache';
|
||||||
|
import {sourceMapLength} from './utils.js';
|
||||||
|
|
||||||
// A rather small cache size, assuming only one module is being linked
|
// A rather small cache size, assuming only one module is being linked
|
||||||
// most of the time.
|
// most of the time.
|
||||||
@@ -14,8 +15,7 @@ const CACHE_SIZE = process.env.METEOR_LINKER_PRELINK_CACHE_SIZE || 1024*1024*20;
|
|||||||
const LINKER_PRELINK_CACHE = new LRU({
|
const LINKER_PRELINK_CACHE = new LRU({
|
||||||
max: CACHE_SIZE,
|
max: CACHE_SIZE,
|
||||||
length: function (prelinked) {
|
length: function (prelinked) {
|
||||||
return prelinked.source.length +
|
return prelinked.source.length + sourceMapLength(prelinked.sourceMap);
|
||||||
prelinked.sourceMap ? prelinked.sourceMap.length : 0;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ _.extend(Module.prototype, {
|
|||||||
}); // results has 'code' and 'map' attributes
|
}); // results has 'code' and 'map' attributes
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const sourceMap = JSON.stringify(results.map.toJSON());
|
const sourceMap = results.map.toJSON();
|
||||||
|
|
||||||
const prelinked = {
|
const prelinked = {
|
||||||
source: results.code,
|
source: results.code,
|
||||||
@@ -175,7 +175,7 @@ _.extend(Module.prototype, {
|
|||||||
return [{
|
return [{
|
||||||
source: results.code,
|
source: results.code,
|
||||||
servePath: self.combinedServePath,
|
servePath: self.combinedServePath,
|
||||||
sourceMap: results.map.toString()
|
sourceMap: results.map.toJSON()
|
||||||
}];
|
}];
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -252,6 +252,7 @@ var File = function (inputFile, module) {
|
|||||||
self.bare = !!inputFile.bare;
|
self.bare = !!inputFile.bare;
|
||||||
|
|
||||||
// A source map (generated by something like CoffeeScript) for the input file.
|
// A source map (generated by something like CoffeeScript) for the input file.
|
||||||
|
// Is an Object, not a string.
|
||||||
self.sourceMap = inputFile.sourceMap;
|
self.sourceMap = inputFile.sourceMap;
|
||||||
|
|
||||||
// The Module containing this file.
|
// The Module containing this file.
|
||||||
@@ -765,13 +766,13 @@ var fullLink = Profile("linker.fullLink", function (inputFiles, {
|
|||||||
if (header.charAt(header.length - 1) !== "\n")
|
if (header.charAt(header.length - 1) !== "\n")
|
||||||
header += "\n"; // make sure it's a whole number of lines
|
header += "\n"; // make sure it's a whole number of lines
|
||||||
var headerLines = header.split('\n').length - 1;
|
var headerLines = header.split('\n').length - 1;
|
||||||
var sourceMapJson = JSON.parse(file.sourceMap);
|
var sourceMap = file.sourceMap;
|
||||||
sourceMapJson.mappings = (new Array(headerLines + 1).join(';')) +
|
sourceMap.mappings = (new Array(headerLines + 1).join(';')) +
|
||||||
sourceMapJson.mappings;
|
sourceMap.mappings;
|
||||||
return {
|
return {
|
||||||
source: header + file.source + footer,
|
source: header + file.source + footer,
|
||||||
servePath: file.servePath,
|
servePath: file.servePath,
|
||||||
sourceMap: JSON.stringify(sourceMapJson)
|
sourceMap: sourceMap
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -726,3 +726,14 @@ exports.sha256 = function (contents) {
|
|||||||
hash.update(contents);
|
hash.update(contents);
|
||||||
return hash.digest('base64');
|
return hash.digest('base64');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.sourceMapLength = function (sm) {
|
||||||
|
if (! sm) return 0;
|
||||||
|
// sum the length of sources and the mappings, the size of
|
||||||
|
// metadata is ignored, but it is not a big deal
|
||||||
|
return sm.mappings.length
|
||||||
|
+ (sm.sourcesContent || []).reduce((soFar, current) => {
|
||||||
|
return soFar + (current ? current.length : 0);
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user