253 lines
6.2 KiB
JavaScript
253 lines
6.2 KiB
JavaScript
|
|
/**
|
||
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||
|
|
*
|
||
|
|
* This source code is licensed under the MIT license found in the
|
||
|
|
* LICENSE file in the root directory of this source tree.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* @format
|
||
|
|
*/
|
||
|
|
"use strict";
|
||
|
|
|
||
|
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
||
|
|
try {
|
||
|
|
var info = gen[key](arg);
|
||
|
|
var value = info.value;
|
||
|
|
} catch (error) {
|
||
|
|
reject(error);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (info.done) {
|
||
|
|
resolve(value);
|
||
|
|
} else {
|
||
|
|
Promise.resolve(value).then(_next, _throw);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function _asyncToGenerator(fn) {
|
||
|
|
return function() {
|
||
|
|
var self = this,
|
||
|
|
args = arguments;
|
||
|
|
return new Promise(function(resolve, reject) {
|
||
|
|
var gen = fn.apply(self, args);
|
||
|
|
function _next(value) {
|
||
|
|
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
||
|
|
}
|
||
|
|
function _throw(err) {
|
||
|
|
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
||
|
|
}
|
||
|
|
_next(undefined);
|
||
|
|
});
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
const Consumer = require("./Consumer");
|
||
|
|
|
||
|
|
const Generator = require("./Generator");
|
||
|
|
|
||
|
|
const SourceMap = require("source-map");
|
||
|
|
|
||
|
|
// We need to export this for `metro-symbolicate`
|
||
|
|
const normalizeSourcePath = require("./Consumer/normalizeSourcePath");
|
||
|
|
|
||
|
|
const composeSourceMaps = require("./composeSourceMaps");
|
||
|
|
|
||
|
|
const _require = require("./BundleBuilder"),
|
||
|
|
createIndexMap = _require.createIndexMap,
|
||
|
|
BundleBuilder = _require.BundleBuilder;
|
||
|
|
|
||
|
|
const _require2 = require("./generateFunctionMap"),
|
||
|
|
generateFunctionMap = _require2.generateFunctionMap;
|
||
|
|
|
||
|
|
function fromRawMappingsImpl(isBlocking, onDone, modules, offsetLines) {
|
||
|
|
const modulesToProcess = modules.slice();
|
||
|
|
const generator = new Generator();
|
||
|
|
let carryOver = offsetLines;
|
||
|
|
|
||
|
|
function processNextModule() {
|
||
|
|
if (modulesToProcess.length === 0) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
const mod = modulesToProcess.shift();
|
||
|
|
const code = mod.code,
|
||
|
|
map = mod.map;
|
||
|
|
|
||
|
|
if (Array.isArray(map)) {
|
||
|
|
addMappingsForFile(generator, map, mod, carryOver);
|
||
|
|
} else if (map != null) {
|
||
|
|
throw new Error(
|
||
|
|
`Unexpected module with full source map found: ${mod.path}`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
carryOver = carryOver + countLines(code);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
function workLoop() {
|
||
|
|
const time = process.hrtime();
|
||
|
|
|
||
|
|
while (true) {
|
||
|
|
const isDone = processNextModule();
|
||
|
|
|
||
|
|
if (isDone) {
|
||
|
|
onDone(generator);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!isBlocking) {
|
||
|
|
// Keep the loop running but try to avoid blocking
|
||
|
|
// for too long because this is not in a worker yet.
|
||
|
|
const diff = process.hrtime(time);
|
||
|
|
const NS_IN_MS = 1000000;
|
||
|
|
|
||
|
|
if (diff[1] > 50 * NS_IN_MS) {
|
||
|
|
// We've blocked for more than 50ms.
|
||
|
|
// This code currently runs on the main thread,
|
||
|
|
// so let's give Metro an opportunity to handle requests.
|
||
|
|
setImmediate(workLoop);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
workLoop();
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Creates a source map from modules with "raw mappings", i.e. an array of
|
||
|
|
* tuples with either 2, 4, or 5 elements:
|
||
|
|
* generated line, generated column, source line, source line, symbol name.
|
||
|
|
* Accepts an `offsetLines` argument in case modules' code is to be offset in
|
||
|
|
* the resulting bundle, e.g. by some prefix code.
|
||
|
|
*/
|
||
|
|
|
||
|
|
function fromRawMappings(modules) {
|
||
|
|
let offsetLines =
|
||
|
|
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
||
|
|
let generator;
|
||
|
|
fromRawMappingsImpl(
|
||
|
|
true,
|
||
|
|
g => {
|
||
|
|
generator = g;
|
||
|
|
},
|
||
|
|
modules,
|
||
|
|
offsetLines
|
||
|
|
);
|
||
|
|
|
||
|
|
if (generator == null) {
|
||
|
|
throw new Error("Expected fromRawMappingsImpl() to finish synchronously.");
|
||
|
|
}
|
||
|
|
|
||
|
|
return generator;
|
||
|
|
}
|
||
|
|
|
||
|
|
function fromRawMappingsNonBlocking(_x) {
|
||
|
|
return _fromRawMappingsNonBlocking.apply(this, arguments);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Transforms a standard source map object into a Raw Mappings object, to be
|
||
|
|
* used across the bundler.
|
||
|
|
*/
|
||
|
|
|
||
|
|
function _fromRawMappingsNonBlocking() {
|
||
|
|
_fromRawMappingsNonBlocking = _asyncToGenerator(function*(modules) {
|
||
|
|
let offsetLines =
|
||
|
|
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
||
|
|
return new Promise(resolve => {
|
||
|
|
fromRawMappingsImpl(false, resolve, modules, offsetLines);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
return _fromRawMappingsNonBlocking.apply(this, arguments);
|
||
|
|
}
|
||
|
|
|
||
|
|
function toBabelSegments(sourceMap) {
|
||
|
|
const rawMappings = [];
|
||
|
|
new SourceMap.SourceMapConsumer(sourceMap).eachMapping(map => {
|
||
|
|
rawMappings.push({
|
||
|
|
generated: {
|
||
|
|
line: map.generatedLine,
|
||
|
|
column: map.generatedColumn
|
||
|
|
},
|
||
|
|
original: {
|
||
|
|
line: map.originalLine,
|
||
|
|
column: map.originalColumn
|
||
|
|
},
|
||
|
|
source: map.source,
|
||
|
|
name: map.name
|
||
|
|
});
|
||
|
|
});
|
||
|
|
return rawMappings;
|
||
|
|
}
|
||
|
|
|
||
|
|
function toSegmentTuple(mapping) {
|
||
|
|
const _mapping$generated = mapping.generated,
|
||
|
|
column = _mapping$generated.column,
|
||
|
|
line = _mapping$generated.line;
|
||
|
|
const name = mapping.name,
|
||
|
|
original = mapping.original;
|
||
|
|
|
||
|
|
if (original == null) {
|
||
|
|
return [line, column];
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeof name !== "string") {
|
||
|
|
return [line, column, original.line, original.column];
|
||
|
|
}
|
||
|
|
|
||
|
|
return [line, column, original.line, original.column, name];
|
||
|
|
}
|
||
|
|
|
||
|
|
function addMappingsForFile(generator, mappings, module, carryOver) {
|
||
|
|
generator.startFile(module.path, module.source, module.functionMap);
|
||
|
|
|
||
|
|
for (let i = 0, n = mappings.length; i < n; ++i) {
|
||
|
|
addMapping(generator, mappings[i], carryOver);
|
||
|
|
}
|
||
|
|
|
||
|
|
generator.endFile();
|
||
|
|
}
|
||
|
|
|
||
|
|
function addMapping(generator, mapping, carryOver) {
|
||
|
|
const n = mapping.length;
|
||
|
|
const line = mapping[0] + carryOver; // lines start at 1, columns start at 0
|
||
|
|
|
||
|
|
const column = mapping[1];
|
||
|
|
|
||
|
|
if (n === 2) {
|
||
|
|
generator.addSimpleMapping(line, column);
|
||
|
|
} else if (n === 4) {
|
||
|
|
const sourceMap = mapping;
|
||
|
|
generator.addSourceMapping(line, column, sourceMap[2], sourceMap[3]);
|
||
|
|
} else if (n === 5) {
|
||
|
|
const sourceMap = mapping;
|
||
|
|
generator.addNamedSourceMapping(
|
||
|
|
line,
|
||
|
|
column,
|
||
|
|
sourceMap[2],
|
||
|
|
sourceMap[3],
|
||
|
|
sourceMap[4]
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
throw new Error(`Invalid mapping: [${mapping.join(", ")}]`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function countLines(string) {
|
||
|
|
return string.split("\n").length;
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
BundleBuilder,
|
||
|
|
composeSourceMaps,
|
||
|
|
Consumer,
|
||
|
|
createIndexMap,
|
||
|
|
generateFunctionMap,
|
||
|
|
fromRawMappings,
|
||
|
|
fromRawMappingsNonBlocking,
|
||
|
|
normalizeSourcePath,
|
||
|
|
toBabelSegments,
|
||
|
|
toSegmentTuple
|
||
|
|
};
|