metro-source-map 0.54.1 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * strict-local
8
+ * @format
9
+ */
10
+ "use strict"; // flowlint-next-line untyped-import:off
11
+
12
+ const util = require("source-map/lib/util"); // Extracted from source-map@0.5.6's SourceMapConsumer
13
+
14
+ function normalizeSourcePath(sourceInput, map) {
15
+ const sourceRoot = map.sourceRoot;
16
+ let source = sourceInput;
17
+ source = String(source); // Some source maps produce relative source paths like "./foo.js" instead of
18
+ // "foo.js". Normalize these first so that future comparisons will succeed.
19
+ // See bugzil.la/1090768.
20
+
21
+ source = util.normalize(source); // Always ensure that absolute sources are internally stored relative to
22
+ // the source root, if the source root is absolute. Not doing this would
23
+ // be particularly problematic when the source root is a prefix of the
24
+ // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
25
+
26
+ source =
27
+ sourceRoot != null && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
28
+ ? util.relative(sourceRoot, source)
29
+ : source;
30
+ return source;
31
+ }
32
+
33
+ module.exports = normalizeSourcePath;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ // flowlint-next-line untyped-import:off
14
+ const util = require('source-map/lib/util');
15
+
16
+ // Extracted from source-map@0.5.6's SourceMapConsumer
17
+ function normalizeSourcePath(
18
+ sourceInput: string,
19
+ map: {+sourceRoot?: ?string},
20
+ ): string {
21
+ const {sourceRoot} = map;
22
+ let source = sourceInput;
23
+
24
+ source = String(source);
25
+ // Some source maps produce relative source paths like "./foo.js" instead of
26
+ // "foo.js". Normalize these first so that future comparisons will succeed.
27
+ // See bugzil.la/1090768.
28
+ source = util.normalize(source);
29
+ // Always ensure that absolute sources are internally stored relative to
30
+ // the source root, if the source root is absolute. Not doing this would
31
+ // be particularly problematic when the source root is a prefix of the
32
+ // source (valid, but why??). See github issue #199 and bugzil.la/1188982.
33
+ source =
34
+ sourceRoot != null && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
35
+ ? util.relative(sourceRoot, source)
36
+ : source;
37
+
38
+ return source;
39
+ }
40
+
41
+ module.exports = normalizeSourcePath;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * strict-local
8
+ * @format
9
+ */
10
+ "use strict";
11
+
12
+ function _objectSpread(target) {
13
+ for (var i = 1; i < arguments.length; i++) {
14
+ var source = arguments[i] != null ? arguments[i] : {};
15
+ var ownKeys = Object.keys(source);
16
+ if (typeof Object.getOwnPropertySymbols === "function") {
17
+ ownKeys = ownKeys.concat(
18
+ Object.getOwnPropertySymbols(source).filter(function(sym) {
19
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
20
+ })
21
+ );
22
+ }
23
+ ownKeys.forEach(function(key) {
24
+ _defineProperty(target, key, source[key]);
25
+ });
26
+ }
27
+ return target;
28
+ }
29
+
30
+ function _defineProperty(obj, key, value) {
31
+ if (key in obj) {
32
+ Object.defineProperty(obj, key, {
33
+ value: value,
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true
37
+ });
38
+ } else {
39
+ obj[key] = value;
40
+ }
41
+ return obj;
42
+ }
43
+
44
+ const _require = require("ob1"),
45
+ add = _require.add,
46
+ neg = _require.neg;
47
+
48
+ function shiftPositionByOffset(pos, offset) {
49
+ return _objectSpread({}, pos, {
50
+ line: pos.line != null ? add(pos.line, offset.lines) : null,
51
+ column: pos.column != null ? add(pos.column, offset.columns) : null
52
+ });
53
+ }
54
+
55
+ function subtractOffsetFromPosition(pos, offset) {
56
+ return shiftPositionByOffset(pos, {
57
+ lines: neg(offset.lines),
58
+ columns: neg(offset.columns)
59
+ });
60
+ }
61
+
62
+ module.exports = {
63
+ shiftPositionByOffset,
64
+ subtractOffsetFromPosition
65
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const {add, neg} = require('ob1');
14
+
15
+ import type {GeneratedOffset} from './types.flow';
16
+ import type {Number0, Number1} from 'ob1';
17
+
18
+ function shiftPositionByOffset<T: {+line: ?Number1, +column: ?Number0}>(
19
+ pos: T,
20
+ offset: GeneratedOffset,
21
+ ): T {
22
+ return {
23
+ ...pos,
24
+ line: pos.line != null ? add(pos.line, offset.lines) : null,
25
+ column: pos.column != null ? add(pos.column, offset.columns) : null,
26
+ };
27
+ }
28
+
29
+ function subtractOffsetFromPosition<T: {+line: ?Number1, +column: ?Number0}>(
30
+ pos: T,
31
+ offset: GeneratedOffset,
32
+ ): T {
33
+ return shiftPositionByOffset(pos, {
34
+ lines: neg(offset.lines),
35
+ columns: neg(offset.columns),
36
+ });
37
+ }
38
+
39
+ module.exports = {shiftPositionByOffset, subtractOffsetFromPosition};
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * strict-local
8
+ * @format
9
+ */
10
+ "use strict";
11
+
12
+ function greatestLowerBound(elements, target, comparator) {
13
+ let first = 0;
14
+ let it = 0;
15
+ let count = elements.length;
16
+ let step;
17
+
18
+ while (count > 0) {
19
+ it = first;
20
+ step = Math.floor(count / 2);
21
+ it = it + step;
22
+
23
+ if (comparator(target, elements[it]) >= 0) {
24
+ first = ++it;
25
+ count = count - (step + 1);
26
+ } else {
27
+ count = step;
28
+ }
29
+ }
30
+
31
+ return first ? first - 1 : null;
32
+ }
33
+
34
+ module.exports = {
35
+ greatestLowerBound
36
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ function greatestLowerBound<T, U>(
14
+ elements: $ReadOnlyArray<T>,
15
+ target: U,
16
+ comparator: (U, T) => number,
17
+ ): ?number {
18
+ let first = 0;
19
+ let it = 0;
20
+ let count = elements.length;
21
+ let step;
22
+ while (count > 0) {
23
+ it = first;
24
+ step = Math.floor(count / 2);
25
+ it = it + step;
26
+ if (comparator(target, elements[it]) >= 0) {
27
+ first = ++it;
28
+ count = count - (step + 1);
29
+ } else {
30
+ count = step;
31
+ }
32
+ }
33
+ return first ? first - 1 : null;
34
+ }
35
+
36
+ module.exports = {greatestLowerBound};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * strict-local
8
+ * @format
9
+ */
10
+ // NOTE: The linter and formatter are fighting over the following lint rule.
11
+
12
+ /* eslint-disable flowtype/object-type-delimiter */
13
+ "use strict";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow strict-local
8
+ * @format
9
+ */
10
+
11
+ // NOTE: The linter and formatter are fighting over the following lint rule.
12
+ /* eslint-disable flowtype/object-type-delimiter */
13
+
14
+ 'use strict';
15
+
16
+ import type {IterationOrder, LookupBias} from './constants';
17
+ import type {Number0, Number1} from 'ob1';
18
+ export type {IterationOrder, LookupBias};
19
+ export type GeneratedOffset = {|+lines: Number0, +columns: Number0|};
20
+ export type SourcePosition = {
21
+ +source: ?string,
22
+ +line: ?Number1,
23
+ +column: ?Number0,
24
+ +name: ?string,
25
+ };
26
+ export type GeneratedPosition = {+line: Number1, +column: Number0};
27
+ export type GeneratedPositionLookup = {
28
+ +line: ?Number1,
29
+ +column: ?Number0,
30
+ +bias?: LookupBias,
31
+ };
32
+
33
+ export type Mapping = {
34
+ source: ?string,
35
+ generatedLine: Number1,
36
+ generatedColumn: Number0,
37
+ originalLine: ?Number1,
38
+ originalColumn: ?Number0,
39
+ name: ?string,
40
+ };
41
+
42
+ export interface IConsumer {
43
+ originalPositionFor(
44
+ generatedPosition: GeneratedPositionLookup,
45
+ ): SourcePosition;
46
+
47
+ generatedMappings(): Iterable<Mapping>;
48
+
49
+ eachMapping(
50
+ callback: (mapping: Mapping) => mixed,
51
+ context?: mixed,
52
+ order?: IterationOrder,
53
+ ): void;
54
+
55
+ // flowlint unsafe-getters-setters:off
56
+ get file(): ?string;
57
+ }
package/src/Generator.js CHANGED
@@ -70,14 +70,16 @@ class Generator {
70
70
  this.source = -1;
71
71
  this.sources = [];
72
72
  this.sourcesContent = [];
73
+ this.x_facebook_sources = [];
73
74
  }
74
75
  /**
75
76
  * Mark the beginning of a new source file.
76
77
  */
77
78
 
78
- startFile(file, code) {
79
+ startFile(file, code, functionMap) {
79
80
  this.source = this.sources.push(file) - 1;
80
81
  this.sourcesContent.push(code);
82
+ this.x_facebook_sources.push(functionMap ? [functionMap] : null);
81
83
  }
82
84
  /**
83
85
  * Mark the end of the current source file
@@ -157,7 +159,7 @@ class Generator {
157
159
  */
158
160
 
159
161
  toMap(file, options) {
160
- let content;
162
+ let content, sourcesMetadata;
161
163
 
162
164
  if (options && options.excludeSource) {
163
165
  content = {};
@@ -167,6 +169,14 @@ class Generator {
167
169
  };
168
170
  }
169
171
 
172
+ if (this.hasSourcesMetadata()) {
173
+ sourcesMetadata = {
174
+ x_facebook_sources: JSON.parse(JSON.stringify(this.x_facebook_sources))
175
+ };
176
+ } else {
177
+ sourcesMetadata = {};
178
+ }
179
+
170
180
  return _objectSpread(
171
181
  {
172
182
  version: 3,
@@ -174,6 +184,7 @@ class Generator {
174
184
  sources: this.sources.slice()
175
185
  },
176
186
  content,
187
+ sourcesMetadata,
177
188
  {
178
189
  names: this.names.items(),
179
190
  mappings: this.builder.toString()
@@ -187,7 +198,7 @@ class Generator {
187
198
  */
188
199
 
189
200
  toString(file, options) {
190
- let content;
201
+ let content, sourcesMetadata;
191
202
 
192
203
  if (options && options.excludeSource) {
193
204
  content = "";
@@ -195,17 +206,36 @@ class Generator {
195
206
  content = `"sourcesContent":${JSON.stringify(this.sourcesContent)},`;
196
207
  }
197
208
 
209
+ if (this.hasSourcesMetadata()) {
210
+ sourcesMetadata = `"x_facebook_sources":${JSON.stringify(
211
+ this.x_facebook_sources
212
+ )},`;
213
+ } else {
214
+ sourcesMetadata = "";
215
+ }
216
+
198
217
  return (
199
218
  "{" +
200
219
  '"version":3,' +
201
220
  (file ? `"file":${JSON.stringify(file)},` : "") +
202
221
  `"sources":${JSON.stringify(this.sources)},` +
203
222
  content +
223
+ sourcesMetadata +
204
224
  `"names":${JSON.stringify(this.names.items())},` +
205
225
  `"mappings":"${this.builder.toString()}"` +
206
226
  "}"
207
227
  );
208
228
  }
229
+ /**
230
+ * Determine whether we need to write the `x_facebook_sources` field.
231
+ * If the metadata is all `null`s, we can omit the field entirely.
232
+ */
233
+
234
+ hasSourcesMetadata() {
235
+ return this.x_facebook_sources.some(
236
+ metadata => metadata != null && metadata.some(value => value != null)
237
+ );
238
+ }
209
239
  }
210
240
 
211
241
  class IndexedSet {
@@ -12,7 +12,11 @@
12
12
 
13
13
  const B64Builder = require('./B64Builder');
14
14
 
15
- import type {BabelSourceMap} from '@babel/core';
15
+ import type {
16
+ BasicSourceMap,
17
+ FBSourceMetadata,
18
+ FBSourceFunctionMap,
19
+ } from './source-map';
16
20
 
17
21
  /**
18
22
  * Generates a source map from raw mappings.
@@ -39,6 +43,7 @@ class Generator {
39
43
  source: number;
40
44
  sources: Array<string>;
41
45
  sourcesContent: Array<?string>;
46
+ x_facebook_sources: Array<?FBSourceMetadata>;
42
47
 
43
48
  constructor() {
44
49
  this.builder = new B64Builder();
@@ -54,14 +59,16 @@ class Generator {
54
59
  this.source = -1;
55
60
  this.sources = [];
56
61
  this.sourcesContent = [];
62
+ this.x_facebook_sources = [];
57
63
  }
58
64
 
59
65
  /**
60
66
  * Mark the beginning of a new source file.
61
67
  */
62
- startFile(file: string, code: string) {
68
+ startFile(file: string, code: string, functionMap: ?FBSourceFunctionMap) {
63
69
  this.source = this.sources.push(file) - 1;
64
70
  this.sourcesContent.push(code);
71
+ this.x_facebook_sources.push(functionMap ? [functionMap] : null);
65
72
  }
66
73
 
67
74
  /**
@@ -147,8 +154,8 @@ class Generator {
147
154
  /**
148
155
  * Return the source map as object.
149
156
  */
150
- toMap(file?: string, options?: {excludeSource?: boolean}): BabelSourceMap {
151
- let content;
157
+ toMap(file?: string, options?: {excludeSource?: boolean}): BasicSourceMap {
158
+ let content, sourcesMetadata;
152
159
 
153
160
  if (options && options.excludeSource) {
154
161
  content = {};
@@ -156,11 +163,20 @@ class Generator {
156
163
  content = {sourcesContent: this.sourcesContent.slice()};
157
164
  }
158
165
 
166
+ if (this.hasSourcesMetadata()) {
167
+ sourcesMetadata = {
168
+ x_facebook_sources: JSON.parse(JSON.stringify(this.x_facebook_sources)),
169
+ };
170
+ } else {
171
+ sourcesMetadata = {};
172
+ }
173
+
159
174
  return {
160
175
  version: 3,
161
176
  file,
162
177
  sources: this.sources.slice(),
163
178
  ...content,
179
+ ...sourcesMetadata,
164
180
  names: this.names.items(),
165
181
  mappings: this.builder.toString(),
166
182
  };
@@ -172,7 +188,7 @@ class Generator {
172
188
  * This is ~2.5x faster than calling `JSON.stringify(generator.toMap())`
173
189
  */
174
190
  toString(file?: string, options?: {excludeSource?: boolean}): string {
175
- let content;
191
+ let content, sourcesMetadata;
176
192
 
177
193
  if (options && options.excludeSource) {
178
194
  content = '';
@@ -180,17 +196,36 @@ class Generator {
180
196
  content = `"sourcesContent":${JSON.stringify(this.sourcesContent)},`;
181
197
  }
182
198
 
199
+ if (this.hasSourcesMetadata()) {
200
+ sourcesMetadata = `"x_facebook_sources":${JSON.stringify(
201
+ this.x_facebook_sources,
202
+ )},`;
203
+ } else {
204
+ sourcesMetadata = '';
205
+ }
206
+
183
207
  return (
184
208
  '{' +
185
209
  '"version":3,' +
186
210
  (file ? `"file":${JSON.stringify(file)},` : '') +
187
211
  `"sources":${JSON.stringify(this.sources)},` +
188
212
  content +
213
+ sourcesMetadata +
189
214
  `"names":${JSON.stringify(this.names.items())},` +
190
215
  `"mappings":"${this.builder.toString()}"` +
191
216
  '}'
192
217
  );
193
218
  }
219
+
220
+ /**
221
+ * Determine whether we need to write the `x_facebook_sources` field.
222
+ * If the metadata is all `null`s, we can omit the field entirely.
223
+ */
224
+ hasSourcesMetadata(): boolean {
225
+ return this.x_facebook_sources.some(
226
+ metadata => metadata != null && metadata.some(value => value != null),
227
+ );
228
+ }
194
229
  }
195
230
 
196
231
  class IndexedSet {
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ *
8
+ * @format
9
+ */
10
+ "use strict"; // eslint-disable-next-line lint/sort-requires
11
+
12
+ const Consumer = require("./Consumer");
13
+
14
+ const _require = require("source-map"),
15
+ SourceMapGenerator = _require.SourceMapGenerator;
16
+
17
+ // Originally based on https://github.com/jakobwesthoff/source-map-merger
18
+ function composeSourceMaps(maps) {
19
+ // NOTE: require() here to break dependency cycle
20
+ const SourceMetadataMapConsumer = require("metro-symbolicate/src/SourceMetadataMapConsumer");
21
+
22
+ if (maps.length < 1) {
23
+ throw new Error("composeSourceMaps: Expected at least one map");
24
+ }
25
+
26
+ const firstMap = maps[0];
27
+ const consumers = maps
28
+ .map(function(map) {
29
+ return new Consumer(map);
30
+ })
31
+ .reverse();
32
+ const generator = new SourceMapGenerator({
33
+ file: consumers[0].file
34
+ });
35
+ consumers[0].eachMapping(mapping => {
36
+ const original = findOriginalPosition(
37
+ consumers,
38
+ mapping.generatedLine,
39
+ mapping.generatedColumn
40
+ );
41
+ generator.addMapping({
42
+ generated: {
43
+ line: mapping.generatedLine,
44
+ column: mapping.generatedColumn
45
+ },
46
+ original:
47
+ original.line != null
48
+ ? {
49
+ line: original.line,
50
+ column: original.column
51
+ }
52
+ : null,
53
+ source: original.source,
54
+ name: original.name
55
+ });
56
+ });
57
+ const composedMap = generator.toJSON();
58
+ const metadataConsumer = new SourceMetadataMapConsumer(firstMap);
59
+ composedMap.x_facebook_sources = metadataConsumer.toArray(
60
+ composedMap.sources
61
+ );
62
+ return composedMap;
63
+ }
64
+
65
+ function findOriginalPosition(consumers, generatedLine, generatedColumn) {
66
+ let currentLine = generatedLine;
67
+ let currentColumn = generatedColumn;
68
+ let original = {
69
+ line: null,
70
+ column: null,
71
+ source: null,
72
+ name: null
73
+ };
74
+
75
+ for (const consumer of consumers) {
76
+ if (currentLine == null || currentColumn == null) {
77
+ return {
78
+ line: null,
79
+ column: null,
80
+ source: null,
81
+ name: null
82
+ };
83
+ }
84
+
85
+ original = consumer.originalPositionFor({
86
+ line: currentLine,
87
+ column: currentColumn
88
+ });
89
+ currentLine = original.line;
90
+ currentColumn = original.column;
91
+
92
+ if (currentLine == null) {
93
+ return {
94
+ line: null,
95
+ column: null,
96
+ source: null,
97
+ name: null
98
+ };
99
+ }
100
+ }
101
+
102
+ return original;
103
+ }
104
+
105
+ module.exports = composeSourceMaps;