Merge pull request #12277 from ankon/pr/source-loader-sourcemaps

Source-loader: Generate sourcemaps
This commit is contained in:
Michael Shilman 2020-10-07 11:08:15 +08:00 committed by GitHub
commit 3231e8d755
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 8 deletions

View File

@ -40,7 +40,8 @@
"prettier": "~2.0.5",
"react": "^16.8.3",
"react-dom": "^16.8.3",
"regenerator-runtime": "^0.13.3"
"regenerator-runtime": "^0.13.3",
"source-map": "^0.7.3"
},
"publishConfig": {
"access": "public"

View File

@ -1,24 +1,63 @@
import { SourceMapConsumer, SourceNode } from 'source-map';
import { readStory } from './dependencies-lookup/readAsObject';
export function transform(inputSource) {
return readStory(this, inputSource).then((sourceObject) => {
export async function transform(inputSource, inputSourceMap) {
const callback = this.async();
try {
const sourceObject = await readStory(this, inputSource);
// if source-loader had trouble parsing the story exports, return the original story
// example is
// const myStory = () => xxx
// export { myStory }
if (!sourceObject.source || sourceObject.source.length === 0) {
return inputSource;
callback(null, inputSource, inputSourceMap);
return;
}
const { source, sourceJson, addsMap } = sourceObject;
// Use the SourceNode to produce the code. Given that the source mapping here is trivial it's easier to just
// always build a sourcemap rather than to have two different code paths.
let sourceNode;
if (inputSourceMap) {
// The inputSourceMap here should be a SourceMapGenerator, or just a plain source map JSON object.
sourceNode = await SourceMapConsumer.with(
JSON.stringify(inputSourceMap),
null,
(consumer) => {
return SourceNode.fromStringWithSourceMap(source, consumer);
}
);
} else {
// Build an identity sourcemap. Note that "source" is already potentially differing from "inputSource"
// due to other loaders, so while we need to use "source" for the source node contents to generate the correct
// code, we still want to use "inputSource" as the source content.
sourceNode = new SourceNode();
sourceNode.add(
source
.split(/\n/)
.map((line, index) => new SourceNode(index + 1, 0, this.resourcePath, `${line}\n`))
);
sourceNode.setSourceContent(this.resourcePath, inputSource);
}
// Prepend the preamble
const preamble = `
/* eslint-disable */
// @ts-nocheck
// @ts-ignore
var __STORY__ = ${sourceJson};
// @ts-ignore
var __LOCATIONS_MAP__ = ${JSON.stringify(addsMap)};
`;
return `${preamble}\n${source}`;
});
var __LOCATIONS_MAP__ = ${JSON.stringify(addsMap)};`;
sourceNode.prepend(`${preamble}\n`);
// Generate the code and the source map for the next loader
const { code, map } = sourceNode.toStringWithSourceMap();
callback(null, code, map);
} catch (e) {
callback(e);
}
}