Add node modules and compiled JavaScript from main

This commit is contained in:
Oliver King 2022-11-02 14:26:33 +00:00
parent 8bccaeaf7c
commit 4181bfdf50
7465 changed files with 1775003 additions and 2 deletions

354
node_modules/v8-to-istanbul/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,354 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [7.1.2](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.1.1...v7.1.2) (2021-05-05)
### Bug Fixes
* fix undefined line in branches and functions ([#139](https://www.github.com/istanbuljs/v8-to-istanbul/issues/139)) ([f5ed83d](https://www.github.com/istanbuljs/v8-to-istanbul/commit/f5ed83d185129db48e5c05c5225470ad114c7609))
### [7.1.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.1.0...v7.1.1) (2021-03-30)
### Bug Fixes
* use original source path if no sources ([#135](https://www.github.com/istanbuljs/v8-to-istanbul/issues/135)) ([64b2c86](https://www.github.com/istanbuljs/v8-to-istanbul/commit/64b2c86099afe3ea9d484324902d4ec4c3965347))
## [7.1.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v7.0.0...v7.1.0) (2020-12-22)
### Features
* support comment c8 ignore start/stop ([#130](https://www.github.com/istanbuljs/v8-to-istanbul/issues/130)) ([591126b](https://www.github.com/istanbuljs/v8-to-istanbul/commit/591126b102244465b27906cdb8cdb82df1f4e760))
## [7.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v6.0.1...v7.0.0) (2020-10-25)
### ⚠ BREAKING CHANGES
* address off by one error processing branches (#127)
### Bug Fixes
* address off by one error processing branches ([#127](https://www.github.com/istanbuljs/v8-to-istanbul/issues/127)) ([746390f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/746390f871fb2d1c6ec9738892a605a9ea59af5c))
* drop special shebang handling ([#125](https://www.github.com/istanbuljs/v8-to-istanbul/issues/125)) ([0d3b57f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/0d3b57f245003d934c0a824f1b6fe54dcebacdb7))
* shebang handling supported in Node v12 ([#128](https://www.github.com/istanbuljs/v8-to-istanbul/issues/128)) ([522e4c2](https://www.github.com/istanbuljs/v8-to-istanbul/commit/522e4c25e6693e31191b47fc5729b6aff9909ce3))
### [6.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v6.0.0...v6.0.1) (2020-10-08)
### Bug Fixes
* **build:** use new relese-please strategy ([c8edd37](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c8edd3741f803dd7485d01ee6f4fcf6a73570700))
* **source-maps:** reverts off by one fix for ignore ([#123](https://www.github.com/istanbuljs/v8-to-istanbul/issues/123)) ([a886fb8](https://www.github.com/istanbuljs/v8-to-istanbul/commit/a886fb82d7e2c5332c6e507e201a9378dda84f50))
## [6.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v5.0.1...v6.0.0) (2020-10-08)
### ⚠ BREAKING CHANGES
* address off by one error processing branches (#118)
### Features
* add support for 1:1 sourcesContent ([ac3c79a](https://www.github.com/istanbuljs/v8-to-istanbul/commit/ac3c79a688665e9f3f05aafe9295a3d71a21267d))
### Bug Fixes
* address off by one error processing branches ([#118](https://www.github.com/istanbuljs/v8-to-istanbul/issues/118)) ([abe51ea](https://www.github.com/istanbuljs/v8-to-istanbul/commit/abe51ea344171c827a014a8c86b3d3a2be5370ce))
* favor mapping at 0th column ([#120](https://www.github.com/istanbuljs/v8-to-istanbul/issues/120)) ([770f17f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/770f17f49e2bf323bdc26f55f91adfedcbb94e25))
### [5.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v5.0.0...v5.0.1) (2020-08-07)
### Bug Fixes
* add missing type in TS definition ([#113](https://www.github.com/istanbuljs/v8-to-istanbul/issues/113)) ([a14ebc2](https://www.github.com/istanbuljs/v8-to-istanbul/commit/a14ebc2f3c71cb854dacb06490ea3e0f9bc17dbd))
## [5.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.4...v5.0.0) (2020-08-02)
### ⚠ BREAKING CHANGES
* drop Node 8 support (#110)
* source map files with multiple sources will now be parsed differently than source map files with a single source.
### Features
* support source map with multiple sources ([#102](https://www.github.com/istanbuljs/v8-to-istanbul/issues/102)) ([d1f435c](https://www.github.com/istanbuljs/v8-to-istanbul/commit/d1f435cf183c510188ec5e43781d5bc10989a4e0)), closes [#21](https://www.github.com/istanbuljs/v8-to-istanbul/issues/21)
### Bug Fixes
* address path related bugs with 1:many source maps ([#108](https://www.github.com/istanbuljs/v8-to-istanbul/issues/108)) ([9a618bc](https://www.github.com/istanbuljs/v8-to-istanbul/commit/9a618bc374ef6e2205c26c5ebf728bc69f4a9288))
### Build System
* drop Node 8 support ([#110](https://www.github.com/istanbuljs/v8-to-istanbul/issues/110)) ([c8bf7a1](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c8bf7a1bdcf8b911943bb1ffc97e401d979aa11f))
### [4.1.4](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.3...v4.1.4) (2020-05-06)
### Bug Fixes
* handle relative sourceRoots in source map files ([#100](https://www.github.com/istanbuljs/v8-to-istanbul/issues/100)) ([16ad3aa](https://www.github.com/istanbuljs/v8-to-istanbul/commit/16ad3aabd6144e2bf15fb4065e697bf40d1caaf4))
### [4.1.3](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.2...v4.1.3) (2020-03-27)
### Bug Fixes
* handle sourcemap `sources` emtpy edge case ([#94](https://www.github.com/istanbuljs/v8-to-istanbul/issues/94)) ([628af48](https://www.github.com/istanbuljs/v8-to-istanbul/commit/628af48e2f7ab279c52f4355c0ccb92ac16b2c1a))
* v8 coverage ranges that fall on \n characters cause exceptions ([#96](https://www.github.com/istanbuljs/v8-to-istanbul/issues/96)) ([c5731a3](https://www.github.com/istanbuljs/v8-to-istanbul/commit/c5731a3b2fe4dccfae9ee581a5bf7a6e362f5cb8))
### [4.1.2](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.1...v4.1.2) (2020-02-09)
### Bug Fixes
* protect against undefined sourcesContent ([#89](https://www.github.com/istanbuljs/v8-to-istanbul/issues/89)) ([5b94fe3](https://www.github.com/istanbuljs/v8-to-istanbul/commit/5b94fe37f9b86686386ad01f1fb8a42182f35ad8))
### [4.1.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.1.0...v4.1.1) (2020-02-07)
### Bug Fixes
* **build:** repository field should have type ([#87](https://www.github.com/istanbuljs/v8-to-istanbul/issues/87)) ([f064542](https://www.github.com/istanbuljs/v8-to-istanbul/commit/f064542844c333d83fc25e0ad7f989f0999f8ceb))
## [4.1.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.0.1...v4.1.0) (2020-02-06)
### Features
* use the inline source content if available ([#85](https://www.github.com/istanbuljs/v8-to-istanbul/issues/85)) ([1a6d47f](https://www.github.com/istanbuljs/v8-to-istanbul/commit/1a6d47f1412d7c2b072fe794b6bd08bfbf4bbd55))
### [4.0.1](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v4.0.0...v4.0.1) (2019-12-12)
### Bug Fixes
* loosen engine requirement so it can be installed on node 8 ([#82](https://www.github.com/istanbuljs/v8-to-istanbul/issues/82)) ([18f2587](https://www.github.com/istanbuljs/v8-to-istanbul/commit/18f2587481617e4db5ae1565c4f7052a8314af92))
## [4.0.0](https://www.github.com/istanbuljs/v8-to-istanbul/compare/v3.2.6...v4.0.0) (2019-11-23)
### ⚠ BREAKING CHANGES
* paths are now consistently absolute.
### Features
* adds special (empty-report) block ([#74](https://www.github.com/istanbuljs/v8-to-istanbul/issues/74)) ([e981cc1](https://www.github.com/istanbuljs/v8-to-istanbul/commit/e981cc156b447ce7a936114dafac591126fd65dd))
### Bug Fixes
* consistently resolve paths to absolute form ([#72](https://www.github.com/istanbuljs/v8-to-istanbul/issues/72)) ([55f4116](https://www.github.com/istanbuljs/v8-to-istanbul/commit/55f411624841f89f8309dc460387f8dd15c8b8f4))
### [3.2.6](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.5...v3.2.6) (2019-10-24)
### Bug Fixes
* remove scheme from paths before joining ([#69](https://github.com/bcoe/v8-to-istanbul/issues/69)) ([10612fa](https://github.com/bcoe/v8-to-istanbul/commit/10612fa))
### [3.2.5](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.4...v3.2.5) (2019-10-07)
### Bug Fixes
* fs.promises was not introduced until 10 ([#67](https://github.com/bcoe/v8-to-istanbul/issues/67)) ([cdcc225](https://github.com/bcoe/v8-to-istanbul/commit/cdcc225))
### [3.2.4](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.3...v3.2.4) (2019-10-06)
### [3.2.3](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.2...v3.2.3) (2019-06-24)
### Bug Fixes
* regex for detecting Node < 10.16 was off ([4ca7220](https://github.com/bcoe/v8-to-istanbul/commit/4ca7220))
### [3.2.2](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.1...v3.2.2) (2019-06-24)
### Bug Fixes
* Node >10.16.0 now uses new module wrap API ([7d7c9cb](https://github.com/bcoe/v8-to-istanbul/commit/7d7c9cb))
### [3.2.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.2.0...v3.2.1) (2019-06-23)
### Bug Fixes
* logic for handling sourceRoot did not take into account process.cwd() ([#39](https://github.com/bcoe/v8-to-istanbul/issues/39)) ([6ed9524](https://github.com/bcoe/v8-to-istanbul/commit/6ed9524))
## [3.2.0](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.3...v3.2.0) (2019-06-23)
### Build System
* update testing matrix and deps ([#34](https://github.com/bcoe/v8-to-istanbul/issues/34)) ([204afca](https://github.com/bcoe/v8-to-istanbul/commit/204afca))
### Features
* add a sources option allowing to bypass fs operations ([#36](https://github.com/bcoe/v8-to-istanbul/issues/36)) ([4f5a681](https://github.com/bcoe/v8-to-istanbul/commit/4f5a681))
* add TS typings ([#35](https://github.com/bcoe/v8-to-istanbul/issues/35)) ([5251108](https://github.com/bcoe/v8-to-istanbul/commit/5251108))
* allow sourceMaps with sourceRoot ([#32](https://github.com/bcoe/v8-to-istanbul/issues/32)) ([8eb2ed0](https://github.com/bcoe/v8-to-istanbul/commit/8eb2ed0))
### [3.1.3](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.2...v3.1.3) (2019-05-11)
### Bug Fixes
* **deps:** source-map should be dependency not dev-dependency ([3f6208e](https://github.com/bcoe/v8-to-istanbul/commit/3f6208e))
## [3.1.2](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.1...v3.1.2) (2019-05-02)
### Bug Fixes
* the line with the ignore comment itself should be skipped ([#25](https://github.com/bcoe/v8-to-istanbul/issues/25)) ([e939594](https://github.com/bcoe/v8-to-istanbul/commit/e939594))
## [3.1.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.1.0...v3.1.1) (2019-05-02)
### Bug Fixes
* we should ignore functions and branches ([#24](https://github.com/bcoe/v8-to-istanbul/issues/24)) ([d468559](https://github.com/bcoe/v8-to-istanbul/commit/d468559))
# [3.1.0](https://github.com/bcoe/v8-to-istanbul/compare/v3.0.1...v3.1.0) (2019-05-02)
### Features
* allow uncovered lines to be ignored with special comment ([#23](https://github.com/bcoe/v8-to-istanbul/issues/23)) ([f585cfa](https://github.com/bcoe/v8-to-istanbul/commit/f585cfa))
## [3.0.1](https://github.com/bcoe/v8-to-istanbul/compare/v3.0.0...v3.0.1) (2019-05-01)
### Bug Fixes
* initial column could be 0 on Node 10, after wrapper taken into account ([#22](https://github.com/bcoe/v8-to-istanbul/issues/22)) ([aa3f73b](https://github.com/bcoe/v8-to-istanbul/commit/aa3f73b))
# [3.0.0](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.2...v3.0.0) (2019-04-29)
### Features
* initial support for source-maps ([#19](https://github.com/bcoe/v8-to-istanbul/issues/19)) ([ab0fcdd](https://github.com/bcoe/v8-to-istanbul/commit/ab0fcdd))
### BREAKING CHANGES
* v8-to-istanbul is now async, making it possible to use the latest source-map library
# [2.1.0](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.5...v2.1.0) (2019-04-21)
### Features
* store source so that it can be used by SourceMaps ([#18](https://github.com/bcoe/v8-to-istanbul/issues/18)) ([5afafd6](https://github.com/bcoe/v8-to-istanbul/commit/5afafd6))
## [2.0.5](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.4...v2.0.5) (2019-04-18)
### Bug Fixes
* don't assume files to have CR characters on Windows ([#16](https://github.com/bcoe/v8-to-istanbul/issues/16)) ([c59a21a](https://github.com/bcoe/v8-to-istanbul/commit/c59a21a))
## [2.0.4](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.3...v2.0.4) (2019-04-07)
### Bug Fixes
* Node 11 no longer wraps scripts by default ([#15](https://github.com/bcoe/v8-to-istanbul/issues/15)) ([fbbd113](https://github.com/bcoe/v8-to-istanbul/commit/fbbd113))
## [2.0.3](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.2...v2.0.3) (2019-04-07)
<a name="2.0.2"></a>
## [2.0.2](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.1...v2.0.2) (2019-01-20)
### Bug Fixes
* windows has \r\n line separator ([#11](https://github.com/bcoe/v8-to-istanbul/issues/11)) ([c10b888](https://github.com/bcoe/v8-to-istanbul/commit/c10b888))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/bcoe/v8-to-istanbul/compare/v2.0.0...v2.0.1) (2019-01-20)
### Bug Fixes
* functions were not always counted ([#10](https://github.com/bcoe/v8-to-istanbul/issues/10)) ([464a1f0](https://github.com/bcoe/v8-to-istanbul/commit/464a1f0))
<a name="2.0.0"></a>
# [2.0.0](https://github.com/bcoe/v8-to-istanbul/compare/v1.2.1...v2.0.0) (2018-12-21)
### Features
* allow wrapper length to be configured ([#9](https://github.com/bcoe/v8-to-istanbul/issues/9)) ([5e76198](https://github.com/bcoe/v8-to-istanbul/commit/5e76198))
### BREAKING CHANGES
* we no longer attempt to detect ESM modules, rather the consumer sets a wrapper length
<a name="1.2.1"></a>
## [1.2.1](https://github.com/bcoe/v8-to-istanbul/compare/v1.2.0...v1.2.1) (2018-09-12)
<a name="1.2.0"></a>
# [1.2.0](https://github.com/bcoe/v8-to-istanbul/compare/v1.1.0...v1.2.0) (2017-12-05)
### Features
* support ESM modules ([#3](https://github.com/bcoe/v8-to-istanbul/issues/3)) ([992d13a](https://github.com/bcoe/v8-to-istanbul/commit/992d13a))
<a name="1.1.0"></a>
# 1.1.0 (2017-12-01)
### Features
* initial implementation ([6140c6c](https://github.com/bcoe/v8-to-istanbul/commit/6140c6c))

14
node_modules/v8-to-istanbul/LICENSE.txt generated vendored Normal file
View file

@ -0,0 +1,14 @@
Copyright (c) 2017, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

86
node_modules/v8-to-istanbul/README.md generated vendored Normal file
View file

@ -0,0 +1,86 @@
# v8-to-istanbul
[![Build Status](https://travis-ci.org/istanbuljs/v8-to-istanbul.svg?branch=master)](https://travis-ci.org/istanbuljs/v8-to-istanbul)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
![nycrc config on GitHub](https://img.shields.io/nycrc/istanbuljs/v8-to-istanbul)
converts from v8 coverage format to [istanbul's coverage format](https://github.com/gotwarlost/istanbul/blob/master/coverage.json.md).
## Usage
```js
const v8toIstanbul = require('v8-to-istanbul')
// the path to the original source-file is required, as its contents are
// used during the conversion algorithm.
const converter = v8toIstanbul('./path-to-instrumented-file.js')
await converter.load() // this is required due to the async source-map dependency.
// provide an array of coverage information in v8 format.
converter.applyCoverage([
{
"functionName": "",
"ranges": [
{
"startOffset": 0,
"endOffset": 520,
"count": 1
}
],
"isBlockCoverage": true
},
// ...
])
// output coverage information in a form that can
// be consumed by Istanbul.
console.info(JSON.stringify(converter.toIstanbul()))
```
## Ignoring Uncovered Lines
Sometimes you might find yourself wanting to ignore uncovered lines
in your application (for example, perhaps you run your tests in Linux, but
there's code that only executes on Windows).
To ignore lines, use the special comment `/* c8 ignore next */`.
### ignoring the next line
```js
const myVariable = 99
/* c8 ignore next */
if (process.platform === 'win32') console.info('hello world')
```
### ignoring the next N lines
```js
const myVariable = 99
/* c8 ignore next 3 */
if (process.platform === 'win32') {
console.info('hello world')
}
```
### ignoring all lines until told
```js
/* c8 ignore start */
function dontMindMe() {
// ...
}
/* c8 ignore stop */
```
### ignoring the same line as the comment
```js
const myVariable = 99
const os = process.platform === 'darwin' ? 'OSXy' /* c8 ignore next */ : 'Windowsy'
```
## Testing
To execute tests, simply run:
```bash
npm test
```

24
node_modules/v8-to-istanbul/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,24 @@
/// <reference types="node" />
import { Profiler } from 'inspector'
import { CoverageMapData } from 'istanbul-lib-coverage'
import { RawSourceMap } from 'source-map'
declare type Sources =
| {
source: string
}
| {
source: string
originalSource: string
sourceMap: { sourcemap: RawSourceMap }
}
declare class V8ToIstanbul {
load(): Promise<void>
applyCoverage(blocks: ReadonlyArray<Profiler.FunctionCoverage>): void
toIstanbul(): CoverageMapData
}
declare function v8ToIstanbul(scriptPath: string, wrapperLength?: number, sources?: Sources, excludePath?: (path: string) => boolean): V8ToIstanbul
export = v8ToIstanbul

5
node_modules/v8-to-istanbul/index.js generated vendored Normal file
View file

@ -0,0 +1,5 @@
const V8ToIstanbul = require('./lib/v8-to-istanbul')
module.exports = function (path, wrapperLength, sources, excludePath) {
return new V8ToIstanbul(path, wrapperLength, sources, excludePath)
}

28
node_modules/v8-to-istanbul/lib/branch.js generated vendored Normal file
View file

@ -0,0 +1,28 @@
module.exports = class CovBranch {
constructor (startLine, startCol, endLine, endCol, count) {
this.startLine = startLine
this.startCol = startCol
this.endLine = endLine
this.endCol = endCol
this.count = count
}
toIstanbul () {
const location = {
start: {
line: this.startLine,
column: this.startCol
},
end: {
line: this.endLine,
column: this.endCol
}
}
return {
type: 'branch',
line: this.startLine,
loc: location,
locations: [Object.assign({}, location)]
}
}
}

29
node_modules/v8-to-istanbul/lib/function.js generated vendored Normal file
View file

@ -0,0 +1,29 @@
module.exports = class CovFunction {
constructor (name, startLine, startCol, endLine, endCol, count) {
this.name = name
this.startLine = startLine
this.startCol = startCol
this.endLine = endLine
this.endCol = endCol
this.count = count
}
toIstanbul () {
const loc = {
start: {
line: this.startLine,
column: this.startCol
},
end: {
line: this.endLine,
column: this.endCol
}
}
return {
name: this.name,
decl: loc,
loc: loc,
line: this.startLine
}
}
}

34
node_modules/v8-to-istanbul/lib/line.js generated vendored Normal file
View file

@ -0,0 +1,34 @@
module.exports = class CovLine {
constructor (line, startCol, lineStr) {
this.line = line
// note that startCol and endCol are absolute positions
// within a file, not relative to the line.
this.startCol = startCol
// the line length itself does not include the newline characters,
// these are however taken into account when enumerating absolute offset.
const matchedNewLineChar = lineStr.match(/\r?\n$/u)
const newLineLength = matchedNewLineChar ? matchedNewLineChar[0].length : 0
this.endCol = startCol + lineStr.length - newLineLength
// we start with all lines having been executed, and work
// backwards zeroing out lines based on V8 output.
this.count = 1
// set by source.js during parsing, if /* c8 ignore next */ is found.
this.ignore = false
}
toIstanbul () {
return {
start: {
line: this.line,
column: 0
},
end: {
line: this.line,
column: this.endCol - this.startCol
}
}
}
}

247
node_modules/v8-to-istanbul/lib/source.js generated vendored Normal file
View file

@ -0,0 +1,247 @@
const CovLine = require('./line')
const { GREATEST_LOWER_BOUND, LEAST_UPPER_BOUND } = require('source-map').SourceMapConsumer
module.exports = class CovSource {
constructor (sourceRaw, wrapperLength) {
sourceRaw = sourceRaw.trimEnd()
this.lines = []
this.eof = sourceRaw.length
this.shebangLength = getShebangLength(sourceRaw)
this.wrapperLength = wrapperLength - this.shebangLength
this._buildLines(sourceRaw)
}
_buildLines (source) {
let position = 0
let ignoreCount = 0
let ignoreAll = false
for (const [i, lineStr] of source.split(/(?<=\r?\n)/u).entries()) {
const line = new CovLine(i + 1, position, lineStr)
if (ignoreCount > 0) {
line.ignore = true
ignoreCount--
} else if (ignoreAll) {
line.ignore = true
}
this.lines.push(line)
position += lineStr.length
const ignoreToken = this._parseIgnore(lineStr)
if (!ignoreToken) continue
line.ignore = true
if (ignoreToken.count !== undefined) {
ignoreCount = ignoreToken.count
}
if (ignoreToken.start || ignoreToken.stop) {
ignoreAll = ignoreToken.start
ignoreCount = 0
}
}
}
/**
* Parses for comments:
* c8 ignore next
* c8 ignore next 3
* c8 ignore start
* c8 ignore stop
* @param {string} lineStr
* @return {{count?: number, start?: boolean, stop?: boolean}|undefined}
*/
_parseIgnore (lineStr) {
const testIgnoreNextLines = lineStr.match(/^\W*\/\* c8 ignore next (?<count>[0-9]+) *\*\/\W*$/)
if (testIgnoreNextLines) {
return { count: Number(testIgnoreNextLines.groups.count) }
}
// Check if comment is on its own line.
if (lineStr.match(/^\W*\/\* c8 ignore next *\*\/\W*$/)) {
return { count: 1 }
}
if (lineStr.match(/\/\* c8 ignore next \*\//)) {
// Won't ignore successive lines, but the current line will be ignored.
return { count: 0 }
}
const testIgnoreStartStop = lineStr.match(/\/\* c8 ignore (?<mode>start|stop) *\*\//)
if (testIgnoreStartStop) {
if (testIgnoreStartStop.groups.mode === 'start') return { start: true }
if (testIgnoreStartStop.groups.mode === 'stop') return { stop: true }
}
}
// given a start column and end column in absolute offsets within
// a source file (0 - EOF), returns the relative line column positions.
offsetToOriginalRelative (sourceMap, startCol, endCol) {
const lines = this.lines.filter((line, i) => {
return startCol <= line.endCol && endCol >= line.startCol
})
if (!lines.length) return {}
const start = originalPositionTryBoth(
sourceMap,
lines[0].line,
Math.max(0, startCol - lines[0].startCol)
)
let end = originalEndPositionFor(
sourceMap,
lines[lines.length - 1].line,
endCol - lines[lines.length - 1].startCol
)
if (!(start && end)) {
return {}
}
if (!(start.source && end.source)) {
return {}
}
if (start.source !== end.source) {
return {}
}
if (start.line === end.line && start.column === end.column) {
end = sourceMap.originalPositionFor({
line: lines[lines.length - 1].line,
column: endCol - lines[lines.length - 1].startCol,
bias: LEAST_UPPER_BOUND
})
end.column -= 1
}
return {
source: start.source,
startLine: start.line,
relStartCol: start.column,
endLine: end.line,
relEndCol: end.column
}
}
relativeToOffset (line, relCol) {
line = Math.max(line, 1)
if (this.lines[line - 1] === undefined) return this.eof
return Math.min(this.lines[line - 1].startCol + relCol, this.lines[line - 1].endCol)
}
}
// this implementation is pulled over from istanbul-lib-sourcemap:
// https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-lib-source-maps/lib/get-mapping.js
//
/**
* AST ranges are inclusive for start positions and exclusive for end positions.
* Source maps are also logically ranges over text, though interacting with
* them is generally achieved by working with explicit positions.
*
* When finding the _end_ location of an AST item, the range behavior is
* important because what we're asking for is the _end_ of whatever range
* corresponds to the end location we seek.
*
* This boils down to the following steps, conceptually, though the source-map
* library doesn't expose primitives to do this nicely:
*
* 1. Find the range on the generated file that ends at, or exclusively
* contains the end position of the AST node.
* 2. Find the range on the original file that corresponds to
* that generated range.
* 3. Find the _end_ location of that original range.
*/
function originalEndPositionFor (sourceMap, line, column) {
// Given the generated location, find the original location of the mapping
// that corresponds to a range on the generated file that overlaps the
// generated file end location. Note however that this position on its
// own is not useful because it is the position of the _start_ of the range
// on the original file, and we want the _end_ of the range.
const beforeEndMapping = originalPositionTryBoth(
sourceMap,
line,
Math.max(column - 1, 1)
)
if (beforeEndMapping.source === null) {
return null
}
// Convert that original position back to a generated one, with a bump
// to the right, and a rightward bias. Since 'generatedPositionFor' searches
// for mappings in the original-order sorted list, this will find the
// mapping that corresponds to the one immediately after the
// beforeEndMapping mapping.
const afterEndMapping = sourceMap.generatedPositionFor({
source: beforeEndMapping.source,
line: beforeEndMapping.line,
column: beforeEndMapping.column + 1,
bias: LEAST_UPPER_BOUND
})
if (
// If this is null, it means that we've hit the end of the file,
// so we can use Infinity as the end column.
afterEndMapping.line === null ||
// If these don't match, it means that the call to
// 'generatedPositionFor' didn't find any other original mappings on
// the line we gave, so consider the binding to extend to infinity.
sourceMap.originalPositionFor(afterEndMapping).line !==
beforeEndMapping.line
) {
return {
source: beforeEndMapping.source,
line: beforeEndMapping.line,
column: Infinity
}
}
// Convert the end mapping into the real original position.
return sourceMap.originalPositionFor(afterEndMapping)
}
function originalPositionTryBoth (sourceMap, line, column) {
let original = sourceMap.originalPositionFor({
line,
column,
bias: GREATEST_LOWER_BOUND
})
if (original.line === null) {
original = sourceMap.originalPositionFor({
line,
column,
bias: LEAST_UPPER_BOUND
})
}
// The source maps generated by https://github.com/istanbuljs/istanbuljs
// (using @babel/core 7.7.5) have behavior, such that a mapping
// mid-way through a line maps to an earlier line than a mapping
// at position 0. Using the line at positon 0 seems to provide better reports:
//
// if (true) {
// cov_y5divc6zu().b[1][0]++;
// cov_y5divc6zu().s[3]++;
// console.info('reachable');
// } else { ... }
// ^ ^
// l5 l3
const min = sourceMap.originalPositionFor({
line,
column: 0,
bias: GREATEST_LOWER_BOUND
})
if (min.line > original.line) {
original = min
}
return original
}
// Not required since Node 12, see: https://github.com/nodejs/node/pull/27375
const isPreNode12 = /^v1[0-1]\./u.test(process.version)
function getShebangLength (source) {
if (isPreNode12 && source.indexOf('#!') === 0) {
const match = source.match(/(?<shebang>#!.*)/)
if (match) {
return match.groups.shebang.length
}
} else {
return 0
}
}

286
node_modules/v8-to-istanbul/lib/v8-to-istanbul.js generated vendored Normal file
View file

@ -0,0 +1,286 @@
const assert = require('assert')
const convertSourceMap = require('convert-source-map')
const { dirname, isAbsolute, join, resolve } = require('path')
const CovBranch = require('./branch')
const CovFunction = require('./function')
const CovSource = require('./source')
const compatError = Error(`requires Node.js ${require('../package.json').engines.node}`)
let readFile = () => { throw compatError }
try {
readFile = require('fs').promises.readFile
} catch (_err) {
// most likely we're on an older version of Node.js.
}
const { SourceMapConsumer } = require('source-map')
const isOlderNode10 = /^v10\.(([0-9]\.)|(1[0-5]\.))/u.test(process.version)
const isNode8 = /^v8\./.test(process.version)
// Injected when Node.js is loading script into isolate pre Node 10.16.x.
// see: https://github.com/nodejs/node/pull/21573.
const cjsWrapperLength = isOlderNode10 ? require('module').wrapper[0].length : 0
module.exports = class V8ToIstanbul {
constructor (scriptPath, wrapperLength, sources, excludePath) {
assert(typeof scriptPath === 'string', 'scriptPath must be a string')
assert(!isNode8, 'This module does not support node 8 or lower, please upgrade to node 10')
this.path = parsePath(scriptPath)
this.wrapperLength = wrapperLength === undefined ? cjsWrapperLength : wrapperLength
this.excludePath = excludePath || (() => false)
this.sources = sources || {}
this.generatedLines = []
this.branches = {}
this.functions = {}
this.covSources = []
this.rawSourceMap = undefined
this.sourceMap = undefined
this.sourceTranspiled = undefined
// Indicate that this report was generated with placeholder data from
// running --all:
this.all = false
}
async load () {
const rawSource = this.sources.source || await readFile(this.path, 'utf8')
this.rawSourceMap = this.sources.sourceMap ||
// if we find a source-map (either inline, or a .map file) we load
// both the transpiled and original source, both of which are used during
// the backflips we perform to remap absolute to relative positions.
convertSourceMap.fromSource(rawSource) || convertSourceMap.fromMapFileSource(rawSource, dirname(this.path))
if (this.rawSourceMap) {
if (this.rawSourceMap.sourcemap.sources.length > 1) {
this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap)
this.covSources = this.sourceMap.sourcesContent.map((rawSource, i) => ({ source: new CovSource(rawSource, this.wrapperLength), path: this.sourceMap.sources[i] }))
this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength)
} else {
const candidatePath = this.rawSourceMap.sourcemap.sources.length >= 1 ? this.rawSourceMap.sourcemap.sources[0] : this.rawSourceMap.sourcemap.file
this.path = this._resolveSource(this.rawSourceMap, candidatePath || this.path)
this.sourceMap = await new SourceMapConsumer(this.rawSourceMap.sourcemap)
let originalRawSource
if (this.sources.sourceMap && this.sources.sourceMap.sourcemap && this.sources.sourceMap.sourcemap.sourcesContent && this.sources.sourceMap.sourcemap.sourcesContent.length === 1) {
// If the sourcesContent field has been provided, return it rather than attempting
// to load the original source from disk.
// TODO: investigate whether there's ever a case where we hit this logic with 1:many sources.
originalRawSource = this.sources.sourceMap.sourcemap.sourcesContent[0]
} else if (this.sources.originalSource) {
// Original source may be populated on the sources object.
originalRawSource = this.sources.originalSource
} else if (this.sourceMap.sourcesContent && this.sourceMap.sourcesContent[0]) {
// perhaps we loaded sourcesContent was populated by an inline source map, or .map file?
// TODO: investigate whether there's ever a case where we hit this logic with 1:many sources.
originalRawSource = this.sourceMap.sourcesContent[0]
} else {
// We fallback to reading the original source from disk.
originalRawSource = await readFile(this.path, 'utf8')
}
this.covSources = [{ source: new CovSource(originalRawSource, this.wrapperLength), path: this.path }]
this.sourceTranspiled = new CovSource(rawSource, this.wrapperLength)
}
} else {
this.covSources = [{ source: new CovSource(rawSource, this.wrapperLength), path: this.path }]
}
}
_resolveSource (rawSourceMap, sourcePath) {
sourcePath = sourcePath.replace(/(^file:\/\/)|(^webpack:\/\/)/, '')
const sourceRoot = rawSourceMap.sourcemap.sourceRoot ? rawSourceMap.sourcemap.sourceRoot.replace('file://', '') : ''
const candidatePath = join(sourceRoot, sourcePath)
if (isAbsolute(candidatePath)) {
return candidatePath
} else {
return resolve(dirname(this.path), candidatePath)
}
}
applyCoverage (blocks) {
blocks.forEach(block => {
block.ranges.forEach((range, i) => {
const { startCol, endCol, path, covSource } = this._maybeRemapStartColEndCol(range)
if (this.excludePath(path)) {
return
}
const lines = covSource.lines.filter(line => {
// Upstream tooling can provide a block with the functionName
// (empty-report), this will result in a report that has all
// lines zeroed out.
if (block.functionName === '(empty-report)') {
line.count = 0
this.all = true
return true
}
return startCol < line.endCol && endCol >= line.startCol
})
const startLineInstance = lines[0]
const endLineInstance = lines[lines.length - 1]
if (block.isBlockCoverage && lines.length) {
this.branches[path] = this.branches[path] || []
// record branches.
this.branches[path].push(new CovBranch(
startLineInstance.line,
startCol - startLineInstance.startCol,
endLineInstance.line,
endCol - endLineInstance.startCol,
range.count
))
// if block-level granularity is enabled, we we still create a single
// CovFunction tracking object for each set of ranges.
if (block.functionName && i === 0) {
this.functions[path] = this.functions[path] || []
this.functions[path].push(new CovFunction(
block.functionName,
startLineInstance.line,
startCol - startLineInstance.startCol,
endLineInstance.line,
endCol - endLineInstance.startCol,
range.count
))
}
} else if (block.functionName && lines.length) {
this.functions[path] = this.functions[path] || []
// record functions.
this.functions[path].push(new CovFunction(
block.functionName,
startLineInstance.line,
startCol - startLineInstance.startCol,
endLineInstance.line,
endCol - endLineInstance.startCol,
range.count
))
}
// record the lines (we record these as statements, such that we're
// compatible with Istanbul 2.0).
lines.forEach(line => {
// make sure branch spans entire line; don't record 'goodbye'
// branch in `const foo = true ? 'hello' : 'goodbye'` as a
// 0 for line coverage.
//
// All lines start out with coverage of 1, and are later set to 0
// if they are not invoked; line.ignore prevents a line from being
// set to 0, and is set if the special comment /* c8 ignore next */
// is used.
if (startCol <= line.startCol && endCol >= line.endCol && !line.ignore) {
line.count = range.count
}
})
})
})
}
_maybeRemapStartColEndCol (range) {
let covSource = this.covSources[0].source
let startCol = Math.max(0, range.startOffset - covSource.wrapperLength)
let endCol = Math.min(covSource.eof, range.endOffset - covSource.wrapperLength)
let path = this.path
if (this.sourceMap) {
startCol = Math.max(0, range.startOffset - this.sourceTranspiled.wrapperLength)
endCol = Math.min(this.sourceTranspiled.eof, range.endOffset - this.sourceTranspiled.wrapperLength)
const { startLine, relStartCol, endLine, relEndCol, source } = this.sourceTranspiled.offsetToOriginalRelative(
this.sourceMap,
startCol,
endCol
)
const matchingSource = this.covSources.find(covSource => covSource.path === source)
covSource = matchingSource ? matchingSource.source : this.covSources[0].source
path = matchingSource ? matchingSource.path : this.covSources[0].path
// next we convert these relative positions back to absolute positions
// in the original source (which is the format expected in the next step).
startCol = covSource.relativeToOffset(startLine, relStartCol)
endCol = covSource.relativeToOffset(endLine, relEndCol)
}
return {
path,
covSource,
startCol,
endCol
}
}
getInnerIstanbul (source, path) {
// We apply the "Resolving Sources" logic (as defined in
// sourcemaps.info/spec.html) as a final step for 1:many source maps.
// for 1:1 source maps, the resolve logic is applied while loading.
//
// TODO: could we move the resolving logic for 1:1 source maps to the final
// step as well? currently this breaks some tests in c8.
let resolvedPath = path
if (this.rawSourceMap && this.rawSourceMap.sourcemap.sources.length > 1) {
resolvedPath = this._resolveSource(this.rawSourceMap, path)
}
if (this.excludePath(resolvedPath)) {
return
}
return {
[resolvedPath]: {
path: resolvedPath,
all: this.all,
...this._statementsToIstanbul(source, path),
...this._branchesToIstanbul(source, path),
...this._functionsToIstanbul(source, path)
}
}
}
toIstanbul () {
return this.covSources.reduce((istanbulOuter, { source, path }) => Object.assign(istanbulOuter, this.getInnerIstanbul(source, path)), {})
}
_statementsToIstanbul (source, path) {
const statements = {
statementMap: {},
s: {}
}
source.lines.forEach((line, index) => {
statements.statementMap[`${index}`] = line.toIstanbul()
statements.s[`${index}`] = line.count
})
return statements
}
_branchesToIstanbul (source, path) {
const branches = {
branchMap: {},
b: {}
}
this.branches[path] = this.branches[path] || []
this.branches[path].forEach((branch, index) => {
const srcLine = source.lines[branch.startLine - 1]
const ignore = srcLine === undefined ? true : srcLine.ignore
branches.branchMap[`${index}`] = branch.toIstanbul()
branches.b[`${index}`] = [ignore ? 1 : branch.count]
})
return branches
}
_functionsToIstanbul (source, path) {
const functions = {
fnMap: {},
f: {}
}
this.functions[path] = this.functions[path] || []
this.functions[path].forEach((fn, index) => {
const srcLine = source.lines[fn.startLine - 1]
const ignore = srcLine === undefined ? true : srcLine.ignore
functions.fnMap[`${index}`] = fn.toIstanbul()
functions.f[`${index}`] = ignore ? 1 : fn.count
})
return functions
}
}
function parsePath (scriptPath) {
return scriptPath.replace('file://', '')
}

View file

@ -0,0 +1,28 @@
Copyright (c) 2009-2011, Mozilla Foundation and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the names of the Mozilla Foundation nor the names of project
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,822 @@
# Source Map
[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map)
[![Coverage Status](https://coveralls.io/repos/github/mozilla/source-map/badge.svg)](https://coveralls.io/github/mozilla/source-map)
[![NPM](https://nodei.co/npm/source-map.png?downloads=true&downloadRank=true)](https://www.npmjs.com/package/source-map)
This is a library to generate and consume the source map format
[described here][format].
[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
## Use with Node
$ npm install source-map
## Use on the Web
<script src="https://unpkg.com/source-map@0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://unpkg.com/source-map@0.7.3/lib/mappings.wasm"
});
</script>
--------------------------------------------------------------------------------
<!-- `npm run toc` to regenerate the Table of Contents -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table of Contents
- [Examples](#examples)
- [Consuming a source map](#consuming-a-source-map)
- [Generating a source map](#generating-a-source-map)
- [With SourceNode (high level API)](#with-sourcenode-high-level-api)
- [With SourceMapGenerator (low level API)](#with-sourcemapgenerator-low-level-api)
- [API](#api)
- [SourceMapConsumer](#sourcemapconsumer)
- [SourceMapConsumer.initialize(options)](#sourcemapconsumerinitializeoptions)
- [new SourceMapConsumer(rawSourceMap)](#new-sourcemapconsumerrawsourcemap)
- [SourceMapConsumer.with](#sourcemapconsumerwith)
- [SourceMapConsumer.prototype.destroy()](#sourcemapconsumerprototypedestroy)
- [SourceMapConsumer.prototype.computeColumnSpans()](#sourcemapconsumerprototypecomputecolumnspans)
- [SourceMapConsumer.prototype.originalPositionFor(generatedPosition)](#sourcemapconsumerprototypeoriginalpositionforgeneratedposition)
- [SourceMapConsumer.prototype.generatedPositionFor(originalPosition)](#sourcemapconsumerprototypegeneratedpositionfororiginalposition)
- [SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition)](#sourcemapconsumerprototypeallgeneratedpositionsfororiginalposition)
- [SourceMapConsumer.prototype.hasContentsOfAllSources()](#sourcemapconsumerprototypehascontentsofallsources)
- [SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing])](#sourcemapconsumerprototypesourcecontentforsource-returnnullonmissing)
- [SourceMapConsumer.prototype.eachMapping(callback, context, order)](#sourcemapconsumerprototypeeachmappingcallback-context-order)
- [SourceMapGenerator](#sourcemapgenerator)
- [new SourceMapGenerator([startOfSourceMap])](#new-sourcemapgeneratorstartofsourcemap)
- [SourceMapGenerator.fromSourceMap(sourceMapConsumer)](#sourcemapgeneratorfromsourcemapsourcemapconsumer)
- [SourceMapGenerator.prototype.addMapping(mapping)](#sourcemapgeneratorprototypeaddmappingmapping)
- [SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)](#sourcemapgeneratorprototypesetsourcecontentsourcefile-sourcecontent)
- [SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]])](#sourcemapgeneratorprototypeapplysourcemapsourcemapconsumer-sourcefile-sourcemappath)
- [SourceMapGenerator.prototype.toString()](#sourcemapgeneratorprototypetostring)
- [SourceNode](#sourcenode)
- [new SourceNode([line, column, source[, chunk[, name]]])](#new-sourcenodeline-column-source-chunk-name)
- [SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath])](#sourcenodefromstringwithsourcemapcode-sourcemapconsumer-relativepath)
- [SourceNode.prototype.add(chunk)](#sourcenodeprototypeaddchunk)
- [SourceNode.prototype.prepend(chunk)](#sourcenodeprototypeprependchunk)
- [SourceNode.prototype.setSourceContent(sourceFile, sourceContent)](#sourcenodeprototypesetsourcecontentsourcefile-sourcecontent)
- [SourceNode.prototype.walk(fn)](#sourcenodeprototypewalkfn)
- [SourceNode.prototype.walkSourceContents(fn)](#sourcenodeprototypewalksourcecontentsfn)
- [SourceNode.prototype.join(sep)](#sourcenodeprototypejoinsep)
- [SourceNode.prototype.replaceRight(pattern, replacement)](#sourcenodeprototypereplacerightpattern-replacement)
- [SourceNode.prototype.toString()](#sourcenodeprototypetostring)
- [SourceNode.prototype.toStringWithSourceMap([startOfSourceMap])](#sourcenodeprototypetostringwithsourcemapstartofsourcemap)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Examples
### Consuming a source map
```js
const rawSourceMap = {
version: 3,
file: 'min.js',
names: ['bar', 'baz', 'n'],
sources: ['one.js', 'two.js'],
sourceRoot: 'http://example.com/www/js/',
mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA'
};
const whatever = await SourceMapConsumer.with(rawSourceMap, null, consumer => {
console.log(consumer.sources);
// [ 'http://example.com/www/js/one.js',
// 'http://example.com/www/js/two.js' ]
console.log(consumer.originalPositionFor({
line: 2,
column: 28
}));
// { source: 'http://example.com/www/js/two.js',
// line: 2,
// column: 10,
// name: 'n' }
console.log(consumer.generatedPositionFor({
source: 'http://example.com/www/js/two.js',
line: 2,
column: 10
}));
// { line: 2, column: 28 }
consumer.eachMapping(function (m) {
// ...
});
return computeWhatever();
});
```
### Generating a source map
In depth guide:
[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/)
#### With SourceNode (high level API)
```js
function compile(ast) {
switch (ast.type) {
case 'BinaryExpression':
return new SourceNode(
ast.location.line,
ast.location.column,
ast.location.source,
[compile(ast.left), " + ", compile(ast.right)]
);
case 'Literal':
return new SourceNode(
ast.location.line,
ast.location.column,
ast.location.source,
String(ast.value)
);
// ...
default:
throw new Error("Bad AST");
}
}
var ast = parse("40 + 2", "add.js");
console.log(compile(ast).toStringWithSourceMap({
file: 'add.js'
}));
// { code: '40 + 2',
// map: [object SourceMapGenerator] }
```
#### With SourceMapGenerator (low level API)
```js
var map = new SourceMapGenerator({
file: "source-mapped.js"
});
map.addMapping({
generated: {
line: 10,
column: 35
},
source: "foo.js",
original: {
line: 33,
column: 2
},
name: "christopher"
});
console.log(map.toString());
// '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}'
```
## API
Get a reference to the module:
```js
// Node.js
var sourceMap = require('source-map');
// Browser builds
var sourceMap = window.sourceMap;
// Inside Firefox
const sourceMap = require("devtools/toolkit/sourcemap/source-map.js");
```
### SourceMapConsumer
A `SourceMapConsumer` instance represents a parsed source map which we can query
for information about the original file positions by giving it a file position
in the generated source.
#### SourceMapConsumer.initialize(options)
When using `SourceMapConsumer` outside of node.js, for example on the Web, it
needs to know from what URL to load `lib/mappings.wasm`. You must inform it by
calling `initialize` before constructing any `SourceMapConsumer`s.
The options object has the following properties:
* `"lib/mappings.wasm"`: A `String` containing the URL of the
`lib/mappings.wasm` file, or an `ArrayBuffer` with the contents of `lib/mappings.wasm`.
```js
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://example.com/source-map/lib/mappings.wasm"
});
```
#### new SourceMapConsumer(rawSourceMap)
The only parameter is the raw source map (either as a string which can be
`JSON.parse`'d, or an object). According to the spec, source maps have the
following attributes:
* `version`: Which version of the source map spec this map is following.
* `sources`: An array of URLs to the original source files.
* `names`: An array of identifiers which can be referenced by individual
mappings.
* `sourceRoot`: Optional. The URL root from which all sources are relative.
* `sourcesContent`: Optional. An array of contents of the original source files.
* `mappings`: A string of base64 VLQs which contain the actual mappings.
* `file`: Optional. The generated filename this source map is associated with.
The promise of the constructed souce map consumer is returned.
When the `SourceMapConsumer` will no longer be used anymore, you must call its
`destroy` method.
```js
const consumer = await new sourceMap.SourceMapConsumer(rawSourceMapJsonData);
doStuffWith(consumer);
consumer.destroy();
```
Alternatively, you can use `SourceMapConsumer.with` to avoid needing to remember
to call `destroy`.
#### SourceMapConsumer.with
Construct a new `SourceMapConsumer` from `rawSourceMap` and `sourceMapUrl`
(see the `SourceMapConsumer` constructor for details. Then, invoke the `async
function f(SourceMapConsumer) -> T` with the newly constructed consumer, wait
for `f` to complete, call `destroy` on the consumer, and return `f`'s return
value.
You must not use the consumer after `f` completes!
By using `with`, you do not have to remember to manually call `destroy` on
the consumer, since it will be called automatically once `f` completes.
```js
const xSquared = await SourceMapConsumer.with(
myRawSourceMap,
null,
async function (consumer) {
// Use `consumer` inside here and don't worry about remembering
// to call `destroy`.
const x = await whatever(consumer);
return x * x;
}
);
// You may not use that `consumer` anymore out here; it has
// been destroyed. But you can use `xSquared`.
console.log(xSquared);
```
#### SourceMapConsumer.prototype.destroy()
Free this source map consumer's associated wasm data that is manually-managed.
```js
consumer.destroy();
```
Alternatively, you can use `SourceMapConsumer.with` to avoid needing to remember
to call `destroy`.
#### SourceMapConsumer.prototype.computeColumnSpans()
Compute the last column for each generated mapping. The last column is
inclusive.
```js
// Before:
consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" })
// [ { line: 2,
// column: 1 },
// { line: 2,
// column: 10 },
// { line: 2,
// column: 20 } ]
consumer.computeColumnSpans();
// After:
consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" })
// [ { line: 2,
// column: 1,
// lastColumn: 9 },
// { line: 2,
// column: 10,
// lastColumn: 19 },
// { line: 2,
// column: 20,
// lastColumn: Infinity } ]
```
#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition)
Returns the original source, line, and column information for the generated
source's line and column positions provided. The only argument is an object with
the following properties:
* `line`: The line number in the generated source. Line numbers in
this library are 1-based (note that the underlying source map
specification uses 0-based line numbers -- this library handles the
translation).
* `column`: The column number in the generated source. Column numbers
in this library are 0-based.
* `bias`: Either `SourceMapConsumer.GREATEST_LOWER_BOUND` or
`SourceMapConsumer.LEAST_UPPER_BOUND`. Specifies whether to return the closest
element that is smaller than or greater than the one we are searching for,
respectively, if the exact element cannot be found. Defaults to
`SourceMapConsumer.GREATEST_LOWER_BOUND`.
and an object is returned with the following properties:
* `source`: The original source file, or null if this information is not
available.
* `line`: The line number in the original source, or null if this information is
not available. The line number is 1-based.
* `column`: The column number in the original source, or null if this
information is not available. The column number is 0-based.
* `name`: The original identifier, or null if this information is not available.
```js
consumer.originalPositionFor({ line: 2, column: 10 })
// { source: 'foo.coffee',
// line: 2,
// column: 2,
// name: null }
consumer.originalPositionFor({ line: 99999999999999999, column: 999999999999999 })
// { source: null,
// line: null,
// column: null,
// name: null }
```
#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition)
Returns the generated line and column information for the original source,
line, and column positions provided. The only argument is an object with
the following properties:
* `source`: The filename of the original source.
* `line`: The line number in the original source. The line number is
1-based.
* `column`: The column number in the original source. The column
number is 0-based.
and an object is returned with the following properties:
* `line`: The line number in the generated source, or null. The line
number is 1-based.
* `column`: The column number in the generated source, or null. The
column number is 0-based.
```js
consumer.generatedPositionFor({ source: "example.js", line: 2, column: 10 })
// { line: 1,
// column: 56 }
```
#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition)
Returns all generated line and column information for the original source, line,
and column provided. If no column is provided, returns all mappings
corresponding to a either the line we are searching for or the next closest line
that has any mappings. Otherwise, returns all mappings corresponding to the
given line and either the column we are searching for or the next closest column
that has any offsets.
The only argument is an object with the following properties:
* `source`: The filename of the original source.
* `line`: The line number in the original source. The line number is
1-based.
* `column`: Optional. The column number in the original source. The
column number is 0-based.
and an array of objects is returned, each with the following properties:
* `line`: The line number in the generated source, or null. The line
number is 1-based.
* `column`: The column number in the generated source, or null. The
column number is 0-based.
```js
consumer.allGeneratedpositionsfor({ line: 2, source: "foo.coffee" })
// [ { line: 2,
// column: 1 },
// { line: 2,
// column: 10 },
// { line: 2,
// column: 20 } ]
```
#### SourceMapConsumer.prototype.hasContentsOfAllSources()
Return true if we have the embedded source content for every source listed in
the source map, false otherwise.
In other words, if this method returns `true`, then
`consumer.sourceContentFor(s)` will succeed for every source `s` in
`consumer.sources`.
```js
// ...
if (consumer.hasContentsOfAllSources()) {
consumerReadyCallback(consumer);
} else {
fetchSources(consumer, consumerReadyCallback);
}
// ...
```
#### SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing])
Returns the original source content for the source provided. The only
argument is the URL of the original source file.
If the source content for the given source is not found, then an error is
thrown. Optionally, pass `true` as the second param to have `null` returned
instead.
```js
consumer.sources
// [ "my-cool-lib.clj" ]
consumer.sourceContentFor("my-cool-lib.clj")
// "..."
consumer.sourceContentFor("this is not in the source map");
// Error: "this is not in the source map" is not in the source map
consumer.sourceContentFor("this is not in the source map", true);
// null
```
#### SourceMapConsumer.prototype.eachMapping(callback, context, order)
Iterate over each mapping between an original source/line/column and a
generated line/column in this source map.
* `callback`: The function that is called with each mapping. Mappings have the
form `{ source, generatedLine, generatedColumn, originalLine, originalColumn,
name }`
* `context`: Optional. If specified, this object will be the value of `this`
every time that `callback` is called.
* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or
`SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over
the mappings sorted by the generated file's line/column order or the
original's source/line/column order, respectively. Defaults to
`SourceMapConsumer.GENERATED_ORDER`.
```js
consumer.eachMapping(function (m) { console.log(m); })
// ...
// { source: 'illmatic.js',
// generatedLine: 1,
// generatedColumn: 0,
// originalLine: 1,
// originalColumn: 0,
// name: null }
// { source: 'illmatic.js',
// generatedLine: 2,
// generatedColumn: 0,
// originalLine: 2,
// originalColumn: 0,
// name: null }
// ...
```
### SourceMapGenerator
An instance of the SourceMapGenerator represents a source map which is being
built incrementally.
#### new SourceMapGenerator([startOfSourceMap])
You may pass an object with the following properties:
* `file`: The filename of the generated source that this source map is
associated with.
* `sourceRoot`: A root for all relative URLs in this source map.
* `skipValidation`: Optional. When `true`, disables validation of mappings as
they are added. This can improve performance but should be used with
discretion, as a last resort. Even then, one should avoid using this flag when
running tests, if possible.
```js
var generator = new sourceMap.SourceMapGenerator({
file: "my-generated-javascript-file.js",
sourceRoot: "http://example.com/app/js/"
});
```
#### SourceMapGenerator.fromSourceMap(sourceMapConsumer)
Creates a new `SourceMapGenerator` from an existing `SourceMapConsumer` instance.
* `sourceMapConsumer` The SourceMap.
```js
var generator = sourceMap.SourceMapGenerator.fromSourceMap(consumer);
```
#### SourceMapGenerator.prototype.addMapping(mapping)
Add a single mapping from original source line and column to the generated
source's line and column for this source map being created. The mapping object
should have the following properties:
* `generated`: An object with the generated line and column positions.
* `original`: An object with the original line and column positions.
* `source`: The original source file (relative to the sourceRoot).
* `name`: An optional original token name for this mapping.
```js
generator.addMapping({
source: "module-one.scm",
original: { line: 128, column: 0 },
generated: { line: 3, column: 456 }
})
```
#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)
Set the source content for an original source file.
* `sourceFile` the URL of the original source file.
* `sourceContent` the content of the source file.
```js
generator.setSourceContent("module-one.scm",
fs.readFileSync("path/to/module-one.scm"))
```
#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]])
Applies a SourceMap for a source file to the SourceMap.
Each mapping to the supplied source file is rewritten using the
supplied SourceMap. Note: The resolution for the resulting mappings
is the minimum of this map and the supplied map.
* `sourceMapConsumer`: The SourceMap to be applied.
* `sourceFile`: Optional. The filename of the source file.
If omitted, sourceMapConsumer.file will be used, if it exists.
Otherwise an error will be thrown.
* `sourceMapPath`: Optional. The dirname of the path to the SourceMap
to be applied. If relative, it is relative to the SourceMap.
This parameter is needed when the two SourceMaps aren't in the same
directory, and the SourceMap to be applied contains relative source
paths. If so, those relative source paths need to be rewritten
relative to the SourceMap.
If omitted, it is assumed that both SourceMaps are in the same directory,
thus not needing any rewriting. (Supplying `'.'` has the same effect.)
#### SourceMapGenerator.prototype.toString()
Renders the source map being generated to a string.
```js
generator.toString()
// '{"version":3,"sources":["module-one.scm"],"names":[],"mappings":"...snip...","file":"my-generated-javascript-file.js","sourceRoot":"http://example.com/app/js/"}'
```
### SourceNode
SourceNodes provide a way to abstract over interpolating and/or concatenating
snippets of generated JavaScript source code, while maintaining the line and
column information associated between those snippets and the original source
code. This is useful as the final intermediate representation a compiler might
use before outputting the generated JS and source map.
#### new SourceNode([line, column, source[, chunk[, name]]])
* `line`: The original line number associated with this source node, or null if
it isn't associated with an original line. The line number is 1-based.
* `column`: The original column number associated with this source node, or null
if it isn't associated with an original column. The column number
is 0-based.
* `source`: The original source's filename; null if no filename is provided.
* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see
below.
* `name`: Optional. The original identifier.
```js
var node = new SourceNode(1, 2, "a.cpp", [
new SourceNode(3, 4, "b.cpp", "extern int status;\n"),
new SourceNode(5, 6, "c.cpp", "std::string* make_string(size_t n);\n"),
new SourceNode(7, 8, "d.cpp", "int main(int argc, char** argv) {}\n"),
]);
```
#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath])
Creates a SourceNode from generated code and a SourceMapConsumer.
* `code`: The generated code
* `sourceMapConsumer` The SourceMap for the generated code
* `relativePath` The optional path that relative sources in `sourceMapConsumer`
should be relative to.
```js
const consumer = await new SourceMapConsumer(fs.readFileSync("path/to/my-file.js.map", "utf8"));
const node = SourceNode.fromStringWithSourceMap(fs.readFileSync("path/to/my-file.js"), consumer);
```
#### SourceNode.prototype.add(chunk)
Add a chunk of generated JS to this source node.
* `chunk`: A string snippet of generated JS code, another instance of
`SourceNode`, or an array where each member is one of those things.
```js
node.add(" + ");
node.add(otherNode);
node.add([leftHandOperandNode, " + ", rightHandOperandNode]);
```
#### SourceNode.prototype.prepend(chunk)
Prepend a chunk of generated JS to this source node.
* `chunk`: A string snippet of generated JS code, another instance of
`SourceNode`, or an array where each member is one of those things.
```js
node.prepend("/** Build Id: f783haef86324gf **/\n\n");
```
#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent)
Set the source content for a source file. This will be added to the
`SourceMap` in the `sourcesContent` field.
* `sourceFile`: The filename of the source file
* `sourceContent`: The content of the source file
```js
node.setSourceContent("module-one.scm",
fs.readFileSync("path/to/module-one.scm"))
```
#### SourceNode.prototype.walk(fn)
Walk over the tree of JS snippets in this node and its children. The walking
function is called once for each snippet of JS and is passed that snippet and
the its original associated source's line/column location.
* `fn`: The traversal function.
```js
var node = new SourceNode(1, 2, "a.js", [
new SourceNode(3, 4, "b.js", "uno"),
"dos",
[
"tres",
new SourceNode(5, 6, "c.js", "quatro")
]
]);
node.walk(function (code, loc) { console.log("WALK:", code, loc); })
// WALK: uno { source: 'b.js', line: 3, column: 4, name: null }
// WALK: dos { source: 'a.js', line: 1, column: 2, name: null }
// WALK: tres { source: 'a.js', line: 1, column: 2, name: null }
// WALK: quatro { source: 'c.js', line: 5, column: 6, name: null }
```
#### SourceNode.prototype.walkSourceContents(fn)
Walk over the tree of SourceNodes. The walking function is called for each
source file content and is passed the filename and source content.
* `fn`: The traversal function.
```js
var a = new SourceNode(1, 2, "a.js", "generated from a");
a.setSourceContent("a.js", "original a");
var b = new SourceNode(1, 2, "b.js", "generated from b");
b.setSourceContent("b.js", "original b");
var c = new SourceNode(1, 2, "c.js", "generated from c");
c.setSourceContent("c.js", "original c");
var node = new SourceNode(null, null, null, [a, b, c]);
node.walkSourceContents(function (source, contents) { console.log("WALK:", source, ":", contents); })
// WALK: a.js : original a
// WALK: b.js : original b
// WALK: c.js : original c
```
#### SourceNode.prototype.join(sep)
Like `Array.prototype.join` except for SourceNodes. Inserts the separator
between each of this source node's children.
* `sep`: The separator.
```js
var lhs = new SourceNode(1, 2, "a.rs", "my_copy");
var operand = new SourceNode(3, 4, "a.rs", "=");
var rhs = new SourceNode(5, 6, "a.rs", "orig.clone()");
var node = new SourceNode(null, null, null, [ lhs, operand, rhs ]);
var joinedNode = node.join(" ");
```
#### SourceNode.prototype.replaceRight(pattern, replacement)
Call `String.prototype.replace` on the very right-most source snippet. Useful
for trimming white space from the end of a source node, etc.
* `pattern`: The pattern to replace.
* `replacement`: The thing to replace the pattern with.
```js
// Trim trailing white space.
node.replaceRight(/\s*$/, "");
```
#### SourceNode.prototype.toString()
Return the string representation of this source node. Walks over the tree and
concatenates all the various snippets together to one string.
```js
var node = new SourceNode(1, 2, "a.js", [
new SourceNode(3, 4, "b.js", "uno"),
"dos",
[
"tres",
new SourceNode(5, 6, "c.js", "quatro")
]
]);
node.toString()
// 'unodostresquatro'
```
#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap])
Returns the string representation of this tree of source nodes, plus a
SourceMapGenerator which contains all the mappings between the generated and
original sources.
The arguments are the same as those to `new SourceMapGenerator`.
```js
var node = new SourceNode(1, 2, "a.js", [
new SourceNode(3, 4, "b.js", "uno"),
"dos",
[
"tres",
new SourceNode(5, 6, "c.js", "quatro")
]
]);
node.toStringWithSourceMap({ file: "my-output-file.js" })
// { code: 'unodostresquatro',
// map: [object SourceMapGenerator] }
```

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,100 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
/**
* A data structure which is a combination of an array and a set. Adding a new
* member is O(1), testing for membership is O(1), and finding the index of an
* element is O(1). Removing elements from the set is not supported. Only
* strings are supported for membership.
*/
class ArraySet {
constructor() {
this._array = [];
this._set = new Map();
}
/**
* Static method for creating ArraySet instances from an existing array.
*/
static fromArray(aArray, aAllowDuplicates) {
const set = new ArraySet();
for (let i = 0, len = aArray.length; i < len; i++) {
set.add(aArray[i], aAllowDuplicates);
}
return set;
}
/**
* Return how many unique items are in this ArraySet. If duplicates have been
* added, than those do not count towards the size.
*
* @returns Number
*/
size() {
return this._set.size;
}
/**
* Add the given string to this set.
*
* @param String aStr
*/
add(aStr, aAllowDuplicates) {
const isDuplicate = this.has(aStr);
const idx = this._array.length;
if (!isDuplicate || aAllowDuplicates) {
this._array.push(aStr);
}
if (!isDuplicate) {
this._set.set(aStr, idx);
}
}
/**
* Is the given string a member of this set?
*
* @param String aStr
*/
has(aStr) {
return this._set.has(aStr);
}
/**
* What is the index of the given string in the array?
*
* @param String aStr
*/
indexOf(aStr) {
const idx = this._set.get(aStr);
if (idx >= 0) {
return idx;
}
throw new Error('"' + aStr + '" is not in the set.');
}
/**
* What is the element at the given index?
*
* @param Number aIdx
*/
at(aIdx) {
if (aIdx >= 0 && aIdx < this._array.length) {
return this._array[aIdx];
}
throw new Error("No element indexed by " + aIdx);
}
/**
* Returns the array representation of this set (which has the proper indices
* indicated by indexOf). Note that this is a copy of the internal array used
* for storing the members so that no one can mess with internal state.
*/
toArray() {
return this._array.slice();
}
}
exports.ArraySet = ArraySet;

View file

@ -0,0 +1,111 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*
* Based on the Base 64 VLQ implementation in Closure Compiler:
* https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
*
* Copyright 2011 The Closure Compiler Authors. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const base64 = require("./base64");
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
// the next four bits are the actual value, and the 6th bit is the
// continuation bit. The continuation bit tells us whether there are more
// digits in this value following this digit.
//
// Continuation
// | Sign
// | |
// V V
// 101011
const VLQ_BASE_SHIFT = 5;
// binary: 100000
const VLQ_BASE = 1 << VLQ_BASE_SHIFT;
// binary: 011111
const VLQ_BASE_MASK = VLQ_BASE - 1;
// binary: 100000
const VLQ_CONTINUATION_BIT = VLQ_BASE;
/**
* Converts from a two-complement value to a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
* 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
*/
function toVLQSigned(aValue) {
return aValue < 0
? ((-aValue) << 1) + 1
: (aValue << 1) + 0;
}
/**
* Converts to a two-complement value from a value where the sign bit is
* placed in the least significant bit. For example, as decimals:
* 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
* 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
*/
// eslint-disable-next-line no-unused-vars
function fromVLQSigned(aValue) {
const isNegative = (aValue & 1) === 1;
const shifted = aValue >> 1;
return isNegative
? -shifted
: shifted;
}
/**
* Returns the base 64 VLQ encoded value.
*/
exports.encode = function base64VLQ_encode(aValue) {
let encoded = "";
let digit;
let vlq = toVLQSigned(aValue);
do {
digit = vlq & VLQ_BASE_MASK;
vlq >>>= VLQ_BASE_SHIFT;
if (vlq > 0) {
// There are still more digits in this value, so we must make sure the
// continuation bit is marked.
digit |= VLQ_CONTINUATION_BIT;
}
encoded += base64.encode(digit);
} while (vlq > 0);
return encoded;
};

View file

@ -0,0 +1,18 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
const intToCharMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");
/**
* Encode an integer in the range of 0 to 63 to a single base 64 digit.
*/
exports.encode = function(number) {
if (0 <= number && number < intToCharMap.length) {
return intToCharMap[number];
}
throw new TypeError("Must be between 0 and 63: " + number);
};

View file

@ -0,0 +1,107 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
exports.GREATEST_LOWER_BOUND = 1;
exports.LEAST_UPPER_BOUND = 2;
/**
* Recursive implementation of binary search.
*
* @param aLow Indices here and lower do not contain the needle.
* @param aHigh Indices here and higher do not contain the needle.
* @param aNeedle The element being searched for.
* @param aHaystack The non-empty array being searched.
* @param aCompare Function which takes two elements and returns -1, 0, or 1.
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
*/
function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
// This function terminates when one of the following is true:
//
// 1. We find the exact element we are looking for.
//
// 2. We did not find the exact element, but we can return the index of
// the next-closest element.
//
// 3. We did not find the exact element, and there is no next-closest
// element than the one we are searching for, so we return -1.
const mid = Math.floor((aHigh - aLow) / 2) + aLow;
const cmp = aCompare(aNeedle, aHaystack[mid], true);
if (cmp === 0) {
// Found the element we are looking for.
return mid;
} else if (cmp > 0) {
// Our needle is greater than aHaystack[mid].
if (aHigh - mid > 1) {
// The element is in the upper half.
return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
}
// The exact needle element was not found in this haystack. Determine if
// we are in termination case (3) or (2) and return the appropriate thing.
if (aBias == exports.LEAST_UPPER_BOUND) {
return aHigh < aHaystack.length ? aHigh : -1;
}
return mid;
}
// Our needle is less than aHaystack[mid].
if (mid - aLow > 1) {
// The element is in the lower half.
return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
}
// we are in termination case (3) or (2) and return the appropriate thing.
if (aBias == exports.LEAST_UPPER_BOUND) {
return mid;
}
return aLow < 0 ? -1 : aLow;
}
/**
* This is an implementation of binary search which will always try and return
* the index of the closest element if there is no exact hit. This is because
* mappings between original and generated line/col pairs are single points,
* and there is an implicit region between each of them, so a miss just means
* that you aren't on the very start of a region.
*
* @param aNeedle The element you are looking for.
* @param aHaystack The array that is being searched.
* @param aCompare A function which takes the needle and an element in the
* array and returns -1, 0, or 1 depending on whether the needle is less
* than, equal to, or greater than the element, respectively.
* @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or
* 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.
*/
exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
if (aHaystack.length === 0) {
return -1;
}
let index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,
aCompare, aBias || exports.GREATEST_LOWER_BOUND);
if (index < 0) {
return -1;
}
// We have found either the exact element, or the next-closest element than
// the one we are searching for. However, there may be more than one such
// element. Make sure we always return the smallest of these.
while (index - 1 >= 0) {
if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
break;
}
--index;
}
return index;
};

View file

@ -0,0 +1,80 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2014 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
const util = require("./util");
/**
* Determine whether mappingB is after mappingA with respect to generated
* position.
*/
function generatedPositionAfter(mappingA, mappingB) {
// Optimized for most common case
const lineA = mappingA.generatedLine;
const lineB = mappingB.generatedLine;
const columnA = mappingA.generatedColumn;
const columnB = mappingB.generatedColumn;
return lineB > lineA || lineB == lineA && columnB >= columnA ||
util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
}
/**
* A data structure to provide a sorted view of accumulated mappings in a
* performance conscious manner. It trades a negligible overhead in general
* case for a large speedup in case of mappings being added in order.
*/
class MappingList {
constructor() {
this._array = [];
this._sorted = true;
// Serves as infimum
this._last = {generatedLine: -1, generatedColumn: 0};
}
/**
* Iterate through internal items. This method takes the same arguments that
* `Array.prototype.forEach` takes.
*
* NOTE: The order of the mappings is NOT guaranteed.
*/
unsortedForEach(aCallback, aThisArg) {
this._array.forEach(aCallback, aThisArg);
}
/**
* Add the given source mapping.
*
* @param Object aMapping
*/
add(aMapping) {
if (generatedPositionAfter(this._last, aMapping)) {
this._last = aMapping;
this._array.push(aMapping);
} else {
this._sorted = false;
this._array.push(aMapping);
}
}
/**
* Returns the flat, sorted array of mappings. The mappings are sorted by
* generated position.
*
* WARNING: This method returns internal data without copying, for
* performance. The return value must NOT be mutated, and should be treated as
* an immutable borrow. If you want to take ownership, you must make your own
* copy.
*/
toArray() {
if (!this._sorted) {
this._array.sort(util.compareByGeneratedPositionsInflated);
this._sorted = true;
}
return this._array;
}
}
exports.MappingList = MappingList;

Binary file not shown.

View file

@ -0,0 +1,49 @@
/* Determine browser vs node environment by testing the default top level context. Solution courtesy of: https://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser */
const isBrowserEnvironment = (function() {
// eslint-disable-next-line no-undef
return (typeof window !== "undefined") && (this === window);
}).call();
if (isBrowserEnvironment) {
// Web version of reading a wasm file into an array buffer.
let mappingsWasm = null;
module.exports = function readWasm() {
if (typeof mappingsWasm === "string") {
return fetch(mappingsWasm)
.then(response => response.arrayBuffer());
}
if (mappingsWasm instanceof ArrayBuffer) {
return Promise.resolve(mappingsWasm);
}
throw new Error("You must provide the string URL or ArrayBuffer contents " +
"of lib/mappings.wasm by calling " +
"SourceMapConsumer.initialize({ 'lib/mappings.wasm': ... }) " +
"before using SourceMapConsumer");
};
module.exports.initialize = input => mappingsWasm = input;
} else {
// Node version of reading a wasm file into an array buffer.
const fs = require("fs");
const path = require("path");
module.exports = function readWasm() {
return new Promise((resolve, reject) => {
const wasmPath = path.join(__dirname, "mappings.wasm");
fs.readFile(wasmPath, null, (error, data) => {
if (error) {
reject(error);
return;
}
resolve(data.buffer);
});
});
};
module.exports.initialize = _ => {
console.debug("SourceMapConsumer.initialize is a no-op when running in node.js");
};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,413 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
const base64VLQ = require("./base64-vlq");
const util = require("./util");
const ArraySet = require("./array-set").ArraySet;
const MappingList = require("./mapping-list").MappingList;
/**
* An instance of the SourceMapGenerator represents a source map which is
* being built incrementally. You may pass an object with the following
* properties:
*
* - file: The filename of the generated source.
* - sourceRoot: A root for all relative URLs in this source map.
*/
class SourceMapGenerator {
constructor(aArgs) {
if (!aArgs) {
aArgs = {};
}
this._file = util.getArg(aArgs, "file", null);
this._sourceRoot = util.getArg(aArgs, "sourceRoot", null);
this._skipValidation = util.getArg(aArgs, "skipValidation", false);
this._sources = new ArraySet();
this._names = new ArraySet();
this._mappings = new MappingList();
this._sourcesContents = null;
}
/**
* Creates a new SourceMapGenerator based on a SourceMapConsumer
*
* @param aSourceMapConsumer The SourceMap.
*/
static fromSourceMap(aSourceMapConsumer) {
const sourceRoot = aSourceMapConsumer.sourceRoot;
const generator = new SourceMapGenerator({
file: aSourceMapConsumer.file,
sourceRoot
});
aSourceMapConsumer.eachMapping(function(mapping) {
const newMapping = {
generated: {
line: mapping.generatedLine,
column: mapping.generatedColumn
}
};
if (mapping.source != null) {
newMapping.source = mapping.source;
if (sourceRoot != null) {
newMapping.source = util.relative(sourceRoot, newMapping.source);
}
newMapping.original = {
line: mapping.originalLine,
column: mapping.originalColumn
};
if (mapping.name != null) {
newMapping.name = mapping.name;
}
}
generator.addMapping(newMapping);
});
aSourceMapConsumer.sources.forEach(function(sourceFile) {
let sourceRelative = sourceFile;
if (sourceRoot !== null) {
sourceRelative = util.relative(sourceRoot, sourceFile);
}
if (!generator._sources.has(sourceRelative)) {
generator._sources.add(sourceRelative);
}
const content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
generator.setSourceContent(sourceFile, content);
}
});
return generator;
}
/**
* Add a single mapping from original source line and column to the generated
* source's line and column for this source map being created. The mapping
* object should have the following properties:
*
* - generated: An object with the generated line and column positions.
* - original: An object with the original line and column positions.
* - source: The original source file (relative to the sourceRoot).
* - name: An optional original token name for this mapping.
*/
addMapping(aArgs) {
const generated = util.getArg(aArgs, "generated");
const original = util.getArg(aArgs, "original", null);
let source = util.getArg(aArgs, "source", null);
let name = util.getArg(aArgs, "name", null);
if (!this._skipValidation) {
this._validateMapping(generated, original, source, name);
}
if (source != null) {
source = String(source);
if (!this._sources.has(source)) {
this._sources.add(source);
}
}
if (name != null) {
name = String(name);
if (!this._names.has(name)) {
this._names.add(name);
}
}
this._mappings.add({
generatedLine: generated.line,
generatedColumn: generated.column,
originalLine: original != null && original.line,
originalColumn: original != null && original.column,
source,
name
});
}
/**
* Set the source content for a source file.
*/
setSourceContent(aSourceFile, aSourceContent) {
let source = aSourceFile;
if (this._sourceRoot != null) {
source = util.relative(this._sourceRoot, source);
}
if (aSourceContent != null) {
// Add the source content to the _sourcesContents map.
// Create a new _sourcesContents map if the property is null.
if (!this._sourcesContents) {
this._sourcesContents = Object.create(null);
}
this._sourcesContents[util.toSetString(source)] = aSourceContent;
} else if (this._sourcesContents) {
// Remove the source file from the _sourcesContents map.
// If the _sourcesContents map is empty, set the property to null.
delete this._sourcesContents[util.toSetString(source)];
if (Object.keys(this._sourcesContents).length === 0) {
this._sourcesContents = null;
}
}
}
/**
* Applies the mappings of a sub-source-map for a specific source file to the
* source map being generated. Each mapping to the supplied source file is
* rewritten using the supplied source map. Note: The resolution for the
* resulting mappings is the minimium of this map and the supplied map.
*
* @param aSourceMapConsumer The source map to be applied.
* @param aSourceFile Optional. The filename of the source file.
* If omitted, SourceMapConsumer's file property will be used.
* @param aSourceMapPath Optional. The dirname of the path to the source map
* to be applied. If relative, it is relative to the SourceMapConsumer.
* This parameter is needed when the two source maps aren't in the same
* directory, and the source map to be applied contains relative source
* paths. If so, those relative source paths need to be rewritten
* relative to the SourceMapGenerator.
*/
applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
let sourceFile = aSourceFile;
// If aSourceFile is omitted, we will use the file property of the SourceMap
if (aSourceFile == null) {
if (aSourceMapConsumer.file == null) {
throw new Error(
"SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, " +
'or the source map\'s "file" property. Both were omitted.'
);
}
sourceFile = aSourceMapConsumer.file;
}
const sourceRoot = this._sourceRoot;
// Make "sourceFile" relative if an absolute Url is passed.
if (sourceRoot != null) {
sourceFile = util.relative(sourceRoot, sourceFile);
}
// Applying the SourceMap can add and remove items from the sources and
// the names array.
const newSources = this._mappings.toArray().length > 0
? new ArraySet()
: this._sources;
const newNames = new ArraySet();
// Find mappings for the "sourceFile"
this._mappings.unsortedForEach(function(mapping) {
if (mapping.source === sourceFile && mapping.originalLine != null) {
// Check if it can be mapped by the source map, then update the mapping.
const original = aSourceMapConsumer.originalPositionFor({
line: mapping.originalLine,
column: mapping.originalColumn
});
if (original.source != null) {
// Copy mapping
mapping.source = original.source;
if (aSourceMapPath != null) {
mapping.source = util.join(aSourceMapPath, mapping.source);
}
if (sourceRoot != null) {
mapping.source = util.relative(sourceRoot, mapping.source);
}
mapping.originalLine = original.line;
mapping.originalColumn = original.column;
if (original.name != null) {
mapping.name = original.name;
}
}
}
const source = mapping.source;
if (source != null && !newSources.has(source)) {
newSources.add(source);
}
const name = mapping.name;
if (name != null && !newNames.has(name)) {
newNames.add(name);
}
}, this);
this._sources = newSources;
this._names = newNames;
// Copy sourcesContents of applied map.
aSourceMapConsumer.sources.forEach(function(srcFile) {
const content = aSourceMapConsumer.sourceContentFor(srcFile);
if (content != null) {
if (aSourceMapPath != null) {
srcFile = util.join(aSourceMapPath, srcFile);
}
if (sourceRoot != null) {
srcFile = util.relative(sourceRoot, srcFile);
}
this.setSourceContent(srcFile, content);
}
}, this);
}
/**
* A mapping can have one of the three levels of data:
*
* 1. Just the generated position.
* 2. The Generated position, original position, and original source.
* 3. Generated and original position, original source, as well as a name
* token.
*
* To maintain consistency, we validate that any new mapping being added falls
* in to one of these categories.
*/
_validateMapping(aGenerated, aOriginal, aSource, aName) {
// When aOriginal is truthy but has empty values for .line and .column,
// it is most likely a programmer error. In this case we throw a very
// specific error message to try to guide them the right way.
// For example: https://github.com/Polymer/polymer-bundler/pull/519
if (aOriginal && typeof aOriginal.line !== "number" && typeof aOriginal.column !== "number") {
throw new Error(
"original.line and original.column are not numbers -- you probably meant to omit " +
"the original mapping entirely and only map the generated position. If so, pass " +
"null for the original mapping instead of an object with empty or null values."
);
}
if (aGenerated && "line" in aGenerated && "column" in aGenerated
&& aGenerated.line > 0 && aGenerated.column >= 0
&& !aOriginal && !aSource && !aName) {
// Case 1.
} else if (aGenerated && "line" in aGenerated && "column" in aGenerated
&& aOriginal && "line" in aOriginal && "column" in aOriginal
&& aGenerated.line > 0 && aGenerated.column >= 0
&& aOriginal.line > 0 && aOriginal.column >= 0
&& aSource) {
// Cases 2 and 3.
} else {
throw new Error("Invalid mapping: " + JSON.stringify({
generated: aGenerated,
source: aSource,
original: aOriginal,
name: aName
}));
}
}
/**
* Serialize the accumulated mappings in to the stream of base 64 VLQs
* specified by the source map format.
*/
_serializeMappings() {
let previousGeneratedColumn = 0;
let previousGeneratedLine = 1;
let previousOriginalColumn = 0;
let previousOriginalLine = 0;
let previousName = 0;
let previousSource = 0;
let result = "";
let next;
let mapping;
let nameIdx;
let sourceIdx;
const mappings = this._mappings.toArray();
for (let i = 0, len = mappings.length; i < len; i++) {
mapping = mappings[i];
next = "";
if (mapping.generatedLine !== previousGeneratedLine) {
previousGeneratedColumn = 0;
while (mapping.generatedLine !== previousGeneratedLine) {
next += ";";
previousGeneratedLine++;
}
} else if (i > 0) {
if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
continue;
}
next += ",";
}
next += base64VLQ.encode(mapping.generatedColumn
- previousGeneratedColumn);
previousGeneratedColumn = mapping.generatedColumn;
if (mapping.source != null) {
sourceIdx = this._sources.indexOf(mapping.source);
next += base64VLQ.encode(sourceIdx - previousSource);
previousSource = sourceIdx;
// lines are stored 0-based in SourceMap spec version 3
next += base64VLQ.encode(mapping.originalLine - 1
- previousOriginalLine);
previousOriginalLine = mapping.originalLine - 1;
next += base64VLQ.encode(mapping.originalColumn
- previousOriginalColumn);
previousOriginalColumn = mapping.originalColumn;
if (mapping.name != null) {
nameIdx = this._names.indexOf(mapping.name);
next += base64VLQ.encode(nameIdx - previousName);
previousName = nameIdx;
}
}
result += next;
}
return result;
}
_generateSourcesContent(aSources, aSourceRoot) {
return aSources.map(function(source) {
if (!this._sourcesContents) {
return null;
}
if (aSourceRoot != null) {
source = util.relative(aSourceRoot, source);
}
const key = util.toSetString(source);
return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
? this._sourcesContents[key]
: null;
}, this);
}
/**
* Externalize the source map.
*/
toJSON() {
const map = {
version: this._version,
sources: this._sources.toArray(),
names: this._names.toArray(),
mappings: this._serializeMappings()
};
if (this._file != null) {
map.file = this._file;
}
if (this._sourceRoot != null) {
map.sourceRoot = this._sourceRoot;
}
if (this._sourcesContents) {
map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
}
return map;
}
/**
* Render the source map being generated to a string.
*/
toString() {
return JSON.stringify(this.toJSON());
}
}
SourceMapGenerator.prototype._version = 3;
exports.SourceMapGenerator = SourceMapGenerator;

View file

@ -0,0 +1,404 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
const SourceMapGenerator = require("./source-map-generator").SourceMapGenerator;
const util = require("./util");
// Matches a Windows-style `\r\n` newline or a `\n` newline used by all other
// operating systems these days (capturing the result).
const REGEX_NEWLINE = /(\r?\n)/;
// Newline character code for charCodeAt() comparisons
const NEWLINE_CODE = 10;
// Private symbol for identifying `SourceNode`s when multiple versions of
// the source-map library are loaded. This MUST NOT CHANGE across
// versions!
const isSourceNode = "$$$isSourceNode$$$";
/**
* SourceNodes provide a way to abstract over interpolating/concatenating
* snippets of generated JavaScript source code while maintaining the line and
* column information associated with the original source code.
*
* @param aLine The original line number.
* @param aColumn The original column number.
* @param aSource The original source's filename.
* @param aChunks Optional. An array of strings which are snippets of
* generated JS, or other SourceNodes.
* @param aName The original identifier.
*/
class SourceNode {
constructor(aLine, aColumn, aSource, aChunks, aName) {
this.children = [];
this.sourceContents = {};
this.line = aLine == null ? null : aLine;
this.column = aColumn == null ? null : aColumn;
this.source = aSource == null ? null : aSource;
this.name = aName == null ? null : aName;
this[isSourceNode] = true;
if (aChunks != null) this.add(aChunks);
}
/**
* Creates a SourceNode from generated code and a SourceMapConsumer.
*
* @param aGeneratedCode The generated code
* @param aSourceMapConsumer The SourceMap for the generated code
* @param aRelativePath Optional. The path that relative sources in the
* SourceMapConsumer should be relative to.
*/
static fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
// The SourceNode we want to fill with the generated code
// and the SourceMap
const node = new SourceNode();
// All even indices of this array are one line of the generated code,
// while all odd indices are the newlines between two adjacent lines
// (since `REGEX_NEWLINE` captures its match).
// Processed fragments are accessed by calling `shiftNextLine`.
const remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
let remainingLinesIndex = 0;
const shiftNextLine = function() {
const lineContents = getNextLine();
// The last line of a file might not have a newline.
const newLine = getNextLine() || "";
return lineContents + newLine;
function getNextLine() {
return remainingLinesIndex < remainingLines.length ?
remainingLines[remainingLinesIndex++] : undefined;
}
};
// We need to remember the position of "remainingLines"
let lastGeneratedLine = 1, lastGeneratedColumn = 0;
// The generate SourceNodes we need a code range.
// To extract it current and last mapping is used.
// Here we store the last mapping.
let lastMapping = null;
let nextLine;
aSourceMapConsumer.eachMapping(function(mapping) {
if (lastMapping !== null) {
// We add the code from "lastMapping" to "mapping":
// First check if there is a new line in between.
if (lastGeneratedLine < mapping.generatedLine) {
// Associate first line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
lastGeneratedLine++;
lastGeneratedColumn = 0;
// The remaining code is added without mapping
} else {
// There is no new line in between.
// Associate the code between "lastGeneratedColumn" and
// "mapping.generatedColumn" with "lastMapping"
nextLine = remainingLines[remainingLinesIndex] || "";
const code = nextLine.substr(0, mapping.generatedColumn -
lastGeneratedColumn);
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn -
lastGeneratedColumn);
lastGeneratedColumn = mapping.generatedColumn;
addMappingWithCode(lastMapping, code);
// No more remaining code, continue
lastMapping = mapping;
return;
}
}
// We add the generated code until the first mapping
// to the SourceNode without any mapping.
// Each line is added as separate string.
while (lastGeneratedLine < mapping.generatedLine) {
node.add(shiftNextLine());
lastGeneratedLine++;
}
if (lastGeneratedColumn < mapping.generatedColumn) {
nextLine = remainingLines[remainingLinesIndex] || "";
node.add(nextLine.substr(0, mapping.generatedColumn));
remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn);
lastGeneratedColumn = mapping.generatedColumn;
}
lastMapping = mapping;
}, this);
// We have processed all mappings.
if (remainingLinesIndex < remainingLines.length) {
if (lastMapping) {
// Associate the remaining code in the current line with "lastMapping"
addMappingWithCode(lastMapping, shiftNextLine());
}
// and add the remaining lines without any mapping
node.add(remainingLines.splice(remainingLinesIndex).join(""));
}
// Copy sourcesContent into SourceNode
aSourceMapConsumer.sources.forEach(function(sourceFile) {
const content = aSourceMapConsumer.sourceContentFor(sourceFile);
if (content != null) {
if (aRelativePath != null) {
sourceFile = util.join(aRelativePath, sourceFile);
}
node.setSourceContent(sourceFile, content);
}
});
return node;
function addMappingWithCode(mapping, code) {
if (mapping === null || mapping.source === undefined) {
node.add(code);
} else {
const source = aRelativePath
? util.join(aRelativePath, mapping.source)
: mapping.source;
node.add(new SourceNode(mapping.originalLine,
mapping.originalColumn,
source,
code,
mapping.name));
}
}
}
/**
* Add a chunk of generated JS to this source node.
*
* @param aChunk A string snippet of generated JS code, another instance of
* SourceNode, or an array where each member is one of those things.
*/
add(aChunk) {
if (Array.isArray(aChunk)) {
aChunk.forEach(function(chunk) {
this.add(chunk);
}, this);
} else if (aChunk[isSourceNode] || typeof aChunk === "string") {
if (aChunk) {
this.children.push(aChunk);
}
} else {
throw new TypeError(
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
);
}
return this;
}
/**
* Add a chunk of generated JS to the beginning of this source node.
*
* @param aChunk A string snippet of generated JS code, another instance of
* SourceNode, or an array where each member is one of those things.
*/
prepend(aChunk) {
if (Array.isArray(aChunk)) {
for (let i = aChunk.length - 1; i >= 0; i--) {
this.prepend(aChunk[i]);
}
} else if (aChunk[isSourceNode] || typeof aChunk === "string") {
this.children.unshift(aChunk);
} else {
throw new TypeError(
"Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk
);
}
return this;
}
/**
* Walk over the tree of JS snippets in this node and its children. The
* walking function is called once for each snippet of JS and is passed that
* snippet and the its original associated source's line/column location.
*
* @param aFn The traversal function.
*/
walk(aFn) {
let chunk;
for (let i = 0, len = this.children.length; i < len; i++) {
chunk = this.children[i];
if (chunk[isSourceNode]) {
chunk.walk(aFn);
} else if (chunk !== "") {
aFn(chunk, { source: this.source,
line: this.line,
column: this.column,
name: this.name });
}
}
}
/**
* Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between
* each of `this.children`.
*
* @param aSep The separator.
*/
join(aSep) {
let newChildren;
let i;
const len = this.children.length;
if (len > 0) {
newChildren = [];
for (i = 0; i < len - 1; i++) {
newChildren.push(this.children[i]);
newChildren.push(aSep);
}
newChildren.push(this.children[i]);
this.children = newChildren;
}
return this;
}
/**
* Call String.prototype.replace on the very right-most source snippet. Useful
* for trimming whitespace from the end of a source node, etc.
*
* @param aPattern The pattern to replace.
* @param aReplacement The thing to replace the pattern with.
*/
replaceRight(aPattern, aReplacement) {
const lastChild = this.children[this.children.length - 1];
if (lastChild[isSourceNode]) {
lastChild.replaceRight(aPattern, aReplacement);
} else if (typeof lastChild === "string") {
this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
} else {
this.children.push("".replace(aPattern, aReplacement));
}
return this;
}
/**
* Set the source content for a source file. This will be added to the SourceMapGenerator
* in the sourcesContent field.
*
* @param aSourceFile The filename of the source file
* @param aSourceContent The content of the source file
*/
setSourceContent(aSourceFile, aSourceContent) {
this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
}
/**
* Walk over the tree of SourceNodes. The walking function is called for each
* source file content and is passed the filename and source content.
*
* @param aFn The traversal function.
*/
walkSourceContents(aFn) {
for (let i = 0, len = this.children.length; i < len; i++) {
if (this.children[i][isSourceNode]) {
this.children[i].walkSourceContents(aFn);
}
}
const sources = Object.keys(this.sourceContents);
for (let i = 0, len = sources.length; i < len; i++) {
aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
}
}
/**
* Return the string representation of this source node. Walks over the tree
* and concatenates all the various snippets together to one string.
*/
toString() {
let str = "";
this.walk(function(chunk) {
str += chunk;
});
return str;
}
/**
* Returns the string representation of this source node along with a source
* map.
*/
toStringWithSourceMap(aArgs) {
const generated = {
code: "",
line: 1,
column: 0
};
const map = new SourceMapGenerator(aArgs);
let sourceMappingActive = false;
let lastOriginalSource = null;
let lastOriginalLine = null;
let lastOriginalColumn = null;
let lastOriginalName = null;
this.walk(function(chunk, original) {
generated.code += chunk;
if (original.source !== null
&& original.line !== null
&& original.column !== null) {
if (lastOriginalSource !== original.source
|| lastOriginalLine !== original.line
|| lastOriginalColumn !== original.column
|| lastOriginalName !== original.name) {
map.addMapping({
source: original.source,
original: {
line: original.line,
column: original.column
},
generated: {
line: generated.line,
column: generated.column
},
name: original.name
});
}
lastOriginalSource = original.source;
lastOriginalLine = original.line;
lastOriginalColumn = original.column;
lastOriginalName = original.name;
sourceMappingActive = true;
} else if (sourceMappingActive) {
map.addMapping({
generated: {
line: generated.line,
column: generated.column
}
});
lastOriginalSource = null;
sourceMappingActive = false;
}
for (let idx = 0, length = chunk.length; idx < length; idx++) {
if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
generated.line++;
generated.column = 0;
// Mappings end at eol
if (idx + 1 === length) {
lastOriginalSource = null;
sourceMappingActive = false;
} else if (sourceMappingActive) {
map.addMapping({
source: original.source,
original: {
line: original.line,
column: original.column
},
generated: {
line: generated.line,
column: generated.column
},
name: original.name
});
}
} else {
generated.column++;
}
}
});
this.walkSourceContents(function(sourceFile, sourceContent) {
map.setSourceContent(sourceFile, sourceContent);
});
return { code: generated.code, map };
}
}
exports.SourceNode = SourceNode;

View file

@ -0,0 +1,546 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
/**
* This is a helper function for getting values from parameter/options
* objects.
*
* @param args The object we are extracting values from
* @param name The name of the property we are getting.
* @param defaultValue An optional value to return if the property is missing
* from the object. If this is not specified and the property is missing, an
* error will be thrown.
*/
function getArg(aArgs, aName, aDefaultValue) {
if (aName in aArgs) {
return aArgs[aName];
} else if (arguments.length === 3) {
return aDefaultValue;
}
throw new Error('"' + aName + '" is a required argument.');
}
exports.getArg = getArg;
const urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
const dataUrlRegexp = /^data:.+\,.+$/;
function urlParse(aUrl) {
const match = aUrl.match(urlRegexp);
if (!match) {
return null;
}
return {
scheme: match[1],
auth: match[2],
host: match[3],
port: match[4],
path: match[5]
};
}
exports.urlParse = urlParse;
function urlGenerate(aParsedUrl) {
let url = "";
if (aParsedUrl.scheme) {
url += aParsedUrl.scheme + ":";
}
url += "//";
if (aParsedUrl.auth) {
url += aParsedUrl.auth + "@";
}
if (aParsedUrl.host) {
url += aParsedUrl.host;
}
if (aParsedUrl.port) {
url += ":" + aParsedUrl.port;
}
if (aParsedUrl.path) {
url += aParsedUrl.path;
}
return url;
}
exports.urlGenerate = urlGenerate;
const MAX_CACHED_INPUTS = 32;
/**
* Takes some function `f(input) -> result` and returns a memoized version of
* `f`.
*
* We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The
* memoization is a dumb-simple, linear least-recently-used cache.
*/
function lruMemoize(f) {
const cache = [];
return function(input) {
for (let i = 0; i < cache.length; i++) {
if (cache[i].input === input) {
const temp = cache[0];
cache[0] = cache[i];
cache[i] = temp;
return cache[0].result;
}
}
const result = f(input);
cache.unshift({
input,
result,
});
if (cache.length > MAX_CACHED_INPUTS) {
cache.pop();
}
return result;
};
}
/**
* Normalizes a path, or the path portion of a URL:
*
* - Replaces consecutive slashes with one slash.
* - Removes unnecessary '.' parts.
* - Removes unnecessary '<dir>/..' parts.
*
* Based on code in the Node.js 'path' core module.
*
* @param aPath The path or url to normalize.
*/
const normalize = lruMemoize(function normalize(aPath) {
let path = aPath;
const url = urlParse(aPath);
if (url) {
if (!url.path) {
return aPath;
}
path = url.path;
}
const isAbsolute = exports.isAbsolute(path);
// Split the path into parts between `/` characters. This is much faster than
// using `.split(/\/+/g)`.
const parts = [];
let start = 0;
let i = 0;
while (true) {
start = i;
i = path.indexOf("/", start);
if (i === -1) {
parts.push(path.slice(start));
break;
} else {
parts.push(path.slice(start, i));
while (i < path.length && path[i] === "/") {
i++;
}
}
}
let up = 0;
for (i = parts.length - 1; i >= 0; i--) {
const part = parts[i];
if (part === ".") {
parts.splice(i, 1);
} else if (part === "..") {
up++;
} else if (up > 0) {
if (part === "") {
// The first part is blank if the path is absolute. Trying to go
// above the root is a no-op. Therefore we can remove all '..' parts
// directly after the root.
parts.splice(i + 1, up);
up = 0;
} else {
parts.splice(i, 2);
up--;
}
}
}
path = parts.join("/");
if (path === "") {
path = isAbsolute ? "/" : ".";
}
if (url) {
url.path = path;
return urlGenerate(url);
}
return path;
});
exports.normalize = normalize;
/**
* Joins two paths/URLs.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be joined with the root.
*
* - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
* scheme-relative URL: Then the scheme of aRoot, if any, is prepended
* first.
* - Otherwise aPath is a path. If aRoot is a URL, then its path portion
* is updated with the result and aRoot is returned. Otherwise the result
* is returned.
* - If aPath is absolute, the result is aPath.
* - Otherwise the two paths are joined with a slash.
* - Joining for example 'http://' and 'www.example.com' is also supported.
*/
function join(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
if (aPath === "") {
aPath = ".";
}
const aPathUrl = urlParse(aPath);
const aRootUrl = urlParse(aRoot);
if (aRootUrl) {
aRoot = aRootUrl.path || "/";
}
// `join(foo, '//www.example.org')`
if (aPathUrl && !aPathUrl.scheme) {
if (aRootUrl) {
aPathUrl.scheme = aRootUrl.scheme;
}
return urlGenerate(aPathUrl);
}
if (aPathUrl || aPath.match(dataUrlRegexp)) {
return aPath;
}
// `join('http://', 'www.example.com')`
if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
aRootUrl.host = aPath;
return urlGenerate(aRootUrl);
}
const joined = aPath.charAt(0) === "/"
? aPath
: normalize(aRoot.replace(/\/+$/, "") + "/" + aPath);
if (aRootUrl) {
aRootUrl.path = joined;
return urlGenerate(aRootUrl);
}
return joined;
}
exports.join = join;
exports.isAbsolute = function(aPath) {
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
};
/**
* Make a path relative to a URL or another path.
*
* @param aRoot The root path or URL.
* @param aPath The path or URL to be made relative to aRoot.
*/
function relative(aRoot, aPath) {
if (aRoot === "") {
aRoot = ".";
}
aRoot = aRoot.replace(/\/$/, "");
// It is possible for the path to be above the root. In this case, simply
// checking whether the root is a prefix of the path won't work. Instead, we
// need to remove components from the root one by one, until either we find
// a prefix that fits, or we run out of components to remove.
let level = 0;
while (aPath.indexOf(aRoot + "/") !== 0) {
const index = aRoot.lastIndexOf("/");
if (index < 0) {
return aPath;
}
// If the only part of the root that is left is the scheme (i.e. http://,
// file:///, etc.), one or more slashes (/), or simply nothing at all, we
// have exhausted all components, so the path is not relative to the root.
aRoot = aRoot.slice(0, index);
if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
return aPath;
}
++level;
}
// Make sure we add a "../" for each component we removed from the root.
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
}
exports.relative = relative;
const supportsNullProto = (function() {
const obj = Object.create(null);
return !("__proto__" in obj);
}());
function identity(s) {
return s;
}
/**
* Because behavior goes wacky when you set `__proto__` on objects, we
* have to prefix all the strings in our set with an arbitrary character.
*
* See https://github.com/mozilla/source-map/pull/31 and
* https://github.com/mozilla/source-map/issues/30
*
* @param String aStr
*/
function toSetString(aStr) {
if (isProtoString(aStr)) {
return "$" + aStr;
}
return aStr;
}
exports.toSetString = supportsNullProto ? identity : toSetString;
function fromSetString(aStr) {
if (isProtoString(aStr)) {
return aStr.slice(1);
}
return aStr;
}
exports.fromSetString = supportsNullProto ? identity : fromSetString;
function isProtoString(s) {
if (!s) {
return false;
}
const length = s.length;
if (length < 9 /* "__proto__".length */) {
return false;
}
/* eslint-disable no-multi-spaces */
if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
s.charCodeAt(length - 2) !== 95 /* '_' */ ||
s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
s.charCodeAt(length - 4) !== 116 /* 't' */ ||
s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
s.charCodeAt(length - 8) !== 95 /* '_' */ ||
s.charCodeAt(length - 9) !== 95 /* '_' */) {
return false;
}
/* eslint-enable no-multi-spaces */
for (let i = length - 10; i >= 0; i--) {
if (s.charCodeAt(i) !== 36 /* '$' */) {
return false;
}
}
return true;
}
/**
* Comparator between two mappings where the original positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same original source/line/column, but different generated
* line and column the same. Useful when searching for a mapping with a
* stubbed out mapping.
*/
function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
let cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0 || onlyCompareOriginal) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByOriginalPositions = compareByOriginalPositions;
/**
* Comparator between two mappings with deflated source and name indices where
* the generated positions are compared.
*
* Optionally pass in `true` as `onlyCompareGenerated` to consider two
* mappings with the same generated line and column, but different
* source/name/original line and column the same. Useful when searching for a
* mapping with a stubbed out mapping.
*/
function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
let cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0 || onlyCompareGenerated) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
function strcmp(aStr1, aStr2) {
if (aStr1 === aStr2) {
return 0;
}
if (aStr1 === null) {
return 1; // aStr2 !== null
}
if (aStr2 === null) {
return -1; // aStr1 !== null
}
if (aStr1 > aStr2) {
return 1;
}
return -1;
}
/**
* Comparator between two mappings with inflated source and name strings where
* the generated positions are compared.
*/
function compareByGeneratedPositionsInflated(mappingA, mappingB) {
let cmp = mappingA.generatedLine - mappingB.generatedLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.generatedColumn - mappingB.generatedColumn;
if (cmp !== 0) {
return cmp;
}
cmp = strcmp(mappingA.source, mappingB.source);
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalLine - mappingB.originalLine;
if (cmp !== 0) {
return cmp;
}
cmp = mappingA.originalColumn - mappingB.originalColumn;
if (cmp !== 0) {
return cmp;
}
return strcmp(mappingA.name, mappingB.name);
}
exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
/**
* Strip any JSON XSSI avoidance prefix from the string (as documented
* in the source maps specification), and then parse the string as
* JSON.
*/
function parseSourceMapInput(str) {
return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ""));
}
exports.parseSourceMapInput = parseSourceMapInput;
/**
* Compute the URL of a source given the the source root, the source's
* URL, and the source map's URL.
*/
function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
sourceURL = sourceURL || "";
if (sourceRoot) {
// This follows what Chrome does.
if (sourceRoot[sourceRoot.length - 1] !== "/" && sourceURL[0] !== "/") {
sourceRoot += "/";
}
// The spec says:
// Line 4: An optional source root, useful for relocating source
// files on a server or removing repeated values in the
// “sources” entry. This value is prepended to the individual
// entries in the “source” field.
sourceURL = sourceRoot + sourceURL;
}
// Historically, SourceMapConsumer did not take the sourceMapURL as
// a parameter. This mode is still somewhat supported, which is why
// this code block is conditional. However, it's preferable to pass
// the source map URL to SourceMapConsumer, so that this function
// can implement the source URL resolution algorithm as outlined in
// the spec. This block is basically the equivalent of:
// new URL(sourceURL, sourceMapURL).toString()
// ... except it avoids using URL, which wasn't available in the
// older releases of node still supported by this library.
//
// The spec says:
// If the sources are not absolute URLs after prepending of the
// “sourceRoot”, the sources are resolved relative to the
// SourceMap (like resolving script src in a html document).
if (sourceMapURL) {
const parsed = urlParse(sourceMapURL);
if (!parsed) {
throw new Error("sourceMapURL could not be parsed");
}
if (parsed.path) {
// Strip the last path component, but keep the "/".
const index = parsed.path.lastIndexOf("/");
if (index >= 0) {
parsed.path = parsed.path.substring(0, index + 1);
}
}
sourceURL = join(urlGenerate(parsed), sourceURL);
}
return normalize(sourceURL);
}
exports.computeSourceURL = computeSourceURL;

View file

@ -0,0 +1,107 @@
const readWasm = require("../lib/read-wasm");
/**
* Provide the JIT with a nice shape / hidden class.
*/
function Mapping() {
this.generatedLine = 0;
this.generatedColumn = 0;
this.lastGeneratedColumn = null;
this.source = null;
this.originalLine = null;
this.originalColumn = null;
this.name = null;
}
let cachedWasm = null;
module.exports = function wasm() {
if (cachedWasm) {
return cachedWasm;
}
const callbackStack = [];
cachedWasm = readWasm().then(buffer => {
return WebAssembly.instantiate(buffer, {
env: {
mapping_callback(
generatedLine,
generatedColumn,
hasLastGeneratedColumn,
lastGeneratedColumn,
hasOriginal,
source,
originalLine,
originalColumn,
hasName,
name
) {
const mapping = new Mapping();
// JS uses 1-based line numbers, wasm uses 0-based.
mapping.generatedLine = generatedLine + 1;
mapping.generatedColumn = generatedColumn;
if (hasLastGeneratedColumn) {
// JS uses inclusive last generated column, wasm uses exclusive.
mapping.lastGeneratedColumn = lastGeneratedColumn - 1;
}
if (hasOriginal) {
mapping.source = source;
// JS uses 1-based line numbers, wasm uses 0-based.
mapping.originalLine = originalLine + 1;
mapping.originalColumn = originalColumn;
if (hasName) {
mapping.name = name;
}
}
callbackStack[callbackStack.length - 1](mapping);
},
start_all_generated_locations_for() { console.time("all_generated_locations_for"); },
end_all_generated_locations_for() { console.timeEnd("all_generated_locations_for"); },
start_compute_column_spans() { console.time("compute_column_spans"); },
end_compute_column_spans() { console.timeEnd("compute_column_spans"); },
start_generated_location_for() { console.time("generated_location_for"); },
end_generated_location_for() { console.timeEnd("generated_location_for"); },
start_original_location_for() { console.time("original_location_for"); },
end_original_location_for() { console.timeEnd("original_location_for"); },
start_parse_mappings() { console.time("parse_mappings"); },
end_parse_mappings() { console.timeEnd("parse_mappings"); },
start_sort_by_generated_location() { console.time("sort_by_generated_location"); },
end_sort_by_generated_location() { console.timeEnd("sort_by_generated_location"); },
start_sort_by_original_location() { console.time("sort_by_original_location"); },
end_sort_by_original_location() { console.timeEnd("sort_by_original_location"); },
}
});
}).then(Wasm => {
return {
exports: Wasm.instance.exports,
withMappingCallback: (mappingCallback, f) => {
callbackStack.push(mappingCallback);
try {
f();
} finally {
callbackStack.pop();
}
}
};
}).then(null, e => {
cachedWasm = null;
throw e;
});
return cachedWasm;
};

View file

@ -0,0 +1,91 @@
{
"name": "source-map",
"description": "Generates and consumes source maps",
"version": "0.7.4",
"homepage": "https://github.com/mozilla/source-map",
"author": "Nick Fitzgerald <nfitzgerald@mozilla.com>",
"contributors": [
"Tobias Koppers <tobias.koppers@googlemail.com>",
"Duncan Beevers <duncan@dweebd.com>",
"Stephen Crane <scrane@mozilla.com>",
"Ryan Seddon <seddon.ryan@gmail.com>",
"Miles Elam <miles.elam@deem.com>",
"Mihai Bazon <mihai.bazon@gmail.com>",
"Michael Ficarra <github.public.email@michael.ficarra.me>",
"Todd Wolfson <todd@twolfson.com>",
"Alexander Solovyov <alexander@solovyov.net>",
"Felix Gnass <fgnass@gmail.com>",
"Conrad Irwin <conrad.irwin@gmail.com>",
"usrbincc <usrbincc@yahoo.com>",
"David Glasser <glasser@davidglasser.net>",
"Chase Douglas <chase@newrelic.com>",
"Evan Wallace <evan.exe@gmail.com>",
"Heather Arthur <fayearthur@gmail.com>",
"Hugh Kennedy <hughskennedy@gmail.com>",
"David Glasser <glasser@davidglasser.net>",
"Simon Lydell <simon.lydell@gmail.com>",
"Jmeas Smith <jellyes2@gmail.com>",
"Michael Z Goddard <mzgoddard@gmail.com>",
"azu <azu@users.noreply.github.com>",
"John Gozde <john@gozde.ca>",
"Adam Kirkton <akirkton@truefitinnovation.com>",
"Chris Montgomery <christopher.montgomery@dowjones.com>",
"J. Ryan Stinnett <jryans@gmail.com>",
"Jack Herrington <jherrington@walmartlabs.com>",
"Chris Truter <jeffpalentine@gmail.com>",
"Daniel Espeset <daniel@danielespeset.com>",
"Jamie Wong <jamie.lf.wong@gmail.com>",
"Eddy Bruël <ejpbruel@mozilla.com>",
"Hawken Rives <hawkrives@gmail.com>",
"Gilad Peleg <giladp007@gmail.com>",
"djchie <djchie.dev@gmail.com>",
"Gary Ye <garysye@gmail.com>",
"Nicolas Lalevée <nicolas.lalevee@hibnet.org>"
],
"repository": {
"type": "git",
"url": "http://github.com/mozilla/source-map.git"
},
"main": "./source-map.js",
"types": "./source-map.d.ts",
"files": [
"source-map.js",
"source-map.d.ts",
"lib/",
"dist/source-map.js"
],
"engines": {
"node": ">= 8"
},
"license": "BSD-3-Clause",
"scripts": {
"lint": "eslint *.js lib/ test/",
"prebuild": "npm run lint",
"build": "webpack --color",
"pretest": "npm run build",
"test": "node test/run-tests.js",
"precoverage": "npm run build",
"coverage": "nyc node test/run-tests.js",
"setup": "mkdir -p coverage && cp -n .waiting.html coverage/index.html || true",
"dev:live": "live-server --port=4103 --ignorePattern='(js|css|png)$' coverage",
"dev:watch": "watch 'npm run coverage' lib/ test/",
"predev": "npm run setup",
"dev": "npm-run-all -p --silent dev:*",
"clean": "rm -rf coverage .nyc_output",
"toc": "doctoc --title '## Table of Contents' README.md && doctoc --title '## Table of Contents' CONTRIBUTING.md"
},
"devDependencies": {
"doctoc": "^1.3.1",
"eslint": "^4.19.1",
"live-server": "^1.2.0",
"npm-run-all": "^4.1.2",
"nyc": "^11.7.1",
"watch": "^1.0.2",
"webpack": "^4.9.1",
"webpack-cli": "^3.1"
},
"nyc": {
"reporter": "html"
},
"typings": "source-map"
}

View file

@ -0,0 +1,369 @@
// Type definitions for source-map 0.7
// Project: https://github.com/mozilla/source-map
// Definitions by: Morten Houston Ludvigsen <https://github.com/MortenHoustonLudvigsen>,
// Ron Buckton <https://github.com/rbuckton>,
// John Vilk <https://github.com/jvilk>
// Definitions: https://github.com/mozilla/source-map
export type SourceMapUrl = string;
export interface StartOfSourceMap {
file?: string;
sourceRoot?: string;
skipValidation?: boolean;
}
export interface RawSourceMap {
version: number;
sources: string[];
names: string[];
sourceRoot?: string;
sourcesContent?: string[];
mappings: string;
file: string;
}
export interface RawIndexMap extends StartOfSourceMap {
version: number;
sections: RawSection[];
}
export interface RawSection {
offset: Position;
map: RawSourceMap;
}
export interface Position {
line: number;
column: number;
}
export interface NullablePosition {
line: number | null;
column: number | null;
lastColumn: number | null;
}
export interface MappedPosition {
source: string;
line: number;
column: number;
name?: string;
}
export interface NullableMappedPosition {
source: string | null;
line: number | null;
column: number | null;
name: string | null;
}
export interface MappingItem {
source: string;
generatedLine: number;
generatedColumn: number;
originalLine: number;
originalColumn: number;
name: string;
}
export interface Mapping {
generated: Position;
original: Position;
source: string;
name?: string;
}
export interface CodeWithSourceMap {
code: string;
map: SourceMapGenerator;
}
export interface SourceMapConsumer {
/**
* Compute the last column for each generated mapping. The last column is
* inclusive.
*/
computeColumnSpans(): void;
/**
* Returns the original source, line, and column information for the generated
* source's line and column positions provided. The only argument is an object
* with the following properties:
*
* - line: The line number in the generated source.
* - column: The column number in the generated source.
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
*
* and an object is returned with the following properties:
*
* - source: The original source file, or null.
* - line: The line number in the original source, or null.
* - column: The column number in the original source, or null.
* - name: The original identifier, or null.
*/
originalPositionFor(generatedPosition: Position & { bias?: number }): NullableMappedPosition;
/**
* Returns the generated line and column information for the original source,
* line, and column positions provided. The only argument is an object with
* the following properties:
*
* - source: The filename of the original source.
* - line: The line number in the original source.
* - column: The column number in the original source.
* - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or
* 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the
* closest element that is smaller than or greater than the one we are
* searching for, respectively, if the exact element cannot be found.
* Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.
*
* and an object is returned with the following properties:
*
* - line: The line number in the generated source, or null.
* - column: The column number in the generated source, or null.
*/
generatedPositionFor(originalPosition: MappedPosition & { bias?: number }): NullablePosition;
/**
* Returns all generated line and column information for the original source,
* line, and column provided. If no column is provided, returns all mappings
* corresponding to a either the line we are searching for or the next
* closest line that has any mappings. Otherwise, returns all mappings
* corresponding to the given line and either the column we are searching for
* or the next closest column that has any offsets.
*
* The only argument is an object with the following properties:
*
* - source: The filename of the original source.
* - line: The line number in the original source.
* - column: Optional. the column number in the original source.
*
* and an array of objects is returned, each with the following properties:
*
* - line: The line number in the generated source, or null.
* - column: The column number in the generated source, or null.
*/
allGeneratedPositionsFor(originalPosition: MappedPosition): NullablePosition[];
/**
* Return true if we have the source content for every source in the source
* map, false otherwise.
*/
hasContentsOfAllSources(): boolean;
/**
* Returns the original source content. The only argument is the url of the
* original source file. Returns null if no original source content is
* available.
*/
sourceContentFor(source: string, returnNullOnMissing?: boolean): string | null;
/**
* Iterate over each mapping between an original source/line/column and a
* generated line/column in this source map.
*
* @param callback
* The function that is called with each mapping.
* @param context
* Optional. If specified, this object will be the value of `this` every
* time that `aCallback` is called.
* @param order
* Either `SourceMapConsumer.GENERATED_ORDER` or
* `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to
* iterate over the mappings sorted by the generated file's line/column
* order or the original's source/line/column order, respectively. Defaults to
* `SourceMapConsumer.GENERATED_ORDER`.
*/
eachMapping(callback: (mapping: MappingItem) => void, context?: any, order?: number): void;
/**
* Free this source map consumer's associated wasm data that is manually-managed.
* Alternatively, you can use SourceMapConsumer.with to avoid needing to remember to call destroy.
*/
destroy(): void;
}
export interface SourceMapConsumerConstructor {
prototype: SourceMapConsumer;
GENERATED_ORDER: number;
ORIGINAL_ORDER: number;
GREATEST_LOWER_BOUND: number;
LEAST_UPPER_BOUND: number;
new (rawSourceMap: RawSourceMap, sourceMapUrl?: SourceMapUrl): Promise<BasicSourceMapConsumer>;
new (rawSourceMap: RawIndexMap, sourceMapUrl?: SourceMapUrl): Promise<IndexedSourceMapConsumer>;
new (rawSourceMap: RawSourceMap | RawIndexMap | string, sourceMapUrl?: SourceMapUrl): Promise<BasicSourceMapConsumer | IndexedSourceMapConsumer>;
/**
* Create a BasicSourceMapConsumer from a SourceMapGenerator.
*
* @param sourceMap
* The source map that will be consumed.
*/
fromSourceMap(sourceMap: SourceMapGenerator, sourceMapUrl?: SourceMapUrl): Promise<BasicSourceMapConsumer>;
/**
* Construct a new `SourceMapConsumer` from `rawSourceMap` and `sourceMapUrl`
* (see the `SourceMapConsumer` constructor for details. Then, invoke the `async
* function f(SourceMapConsumer) -> T` with the newly constructed consumer, wait
* for `f` to complete, call `destroy` on the consumer, and return `f`'s return
* value.
*
* You must not use the consumer after `f` completes!
*
* By using `with`, you do not have to remember to manually call `destroy` on
* the consumer, since it will be called automatically once `f` completes.
*
* ```js
* const xSquared = await SourceMapConsumer.with(
* myRawSourceMap,
* null,
* async function (consumer) {
* // Use `consumer` inside here and don't worry about remembering
* // to call `destroy`.
*
* const x = await whatever(consumer);
* return x * x;
* }
* );
*
* // You may not use that `consumer` anymore out here; it has
* // been destroyed. But you can use `xSquared`.
* console.log(xSquared);
* ```
*/
with<T>(rawSourceMap: RawSourceMap | RawIndexMap | string, sourceMapUrl: SourceMapUrl | null | undefined, callback: (consumer: BasicSourceMapConsumer | IndexedSourceMapConsumer) => Promise<T> | T): Promise<T>;
}
export const SourceMapConsumer: SourceMapConsumerConstructor;
export interface BasicSourceMapConsumer extends SourceMapConsumer {
file: string;
sourceRoot: string;
sources: string[];
sourcesContent: string[];
}
export interface BasicSourceMapConsumerConstructor {
prototype: BasicSourceMapConsumer;
new (rawSourceMap: RawSourceMap | string): Promise<BasicSourceMapConsumer>;
/**
* Create a BasicSourceMapConsumer from a SourceMapGenerator.
*
* @param sourceMap
* The source map that will be consumed.
*/
fromSourceMap(sourceMap: SourceMapGenerator): Promise<BasicSourceMapConsumer>;
}
export const BasicSourceMapConsumer: BasicSourceMapConsumerConstructor;
export interface IndexedSourceMapConsumer extends SourceMapConsumer {
sources: string[];
}
export interface IndexedSourceMapConsumerConstructor {
prototype: IndexedSourceMapConsumer;
new (rawSourceMap: RawIndexMap | string): Promise<IndexedSourceMapConsumer>;
}
export const IndexedSourceMapConsumer: IndexedSourceMapConsumerConstructor;
export class SourceMapGenerator {
constructor(startOfSourceMap?: StartOfSourceMap);
/**
* Creates a new SourceMapGenerator based on a SourceMapConsumer
*
* @param sourceMapConsumer The SourceMap.
*/
static fromSourceMap(sourceMapConsumer: SourceMapConsumer): SourceMapGenerator;
/**
* Add a single mapping from original source line and column to the generated
* source's line and column for this source map being created. The mapping
* object should have the following properties:
*
* - generated: An object with the generated line and column positions.
* - original: An object with the original line and column positions.
* - source: The original source file (relative to the sourceRoot).
* - name: An optional original token name for this mapping.
*/
addMapping(mapping: Mapping): void;
/**
* Set the source content for a source file.
*/
setSourceContent(sourceFile: string, sourceContent: string): void;
/**
* Applies the mappings of a sub-source-map for a specific source file to the
* source map being generated. Each mapping to the supplied source file is
* rewritten using the supplied source map. Note: The resolution for the
* resulting mappings is the minimium of this map and the supplied map.
*
* @param sourceMapConsumer The source map to be applied.
* @param sourceFile Optional. The filename of the source file.
* If omitted, SourceMapConsumer's file property will be used.
* @param sourceMapPath Optional. The dirname of the path to the source map
* to be applied. If relative, it is relative to the SourceMapConsumer.
* This parameter is needed when the two source maps aren't in the same
* directory, and the source map to be applied contains relative source
* paths. If so, those relative source paths need to be rewritten
* relative to the SourceMapGenerator.
*/
applySourceMap(sourceMapConsumer: SourceMapConsumer, sourceFile?: string, sourceMapPath?: string): void;
toString(): string;
toJSON(): RawSourceMap;
}
export class SourceNode {
children: SourceNode[];
sourceContents: any;
line: number;
column: number;
source: string;
name: string;
constructor();
constructor(
line: number | null,
column: number | null,
source: string | null,
chunks?: Array<(string | SourceNode)> | SourceNode | string,
name?: string
);
static fromStringWithSourceMap(
code: string,
sourceMapConsumer: SourceMapConsumer,
relativePath?: string
): SourceNode;
add(chunk: Array<(string | SourceNode)> | SourceNode | string): SourceNode;
prepend(chunk: Array<(string | SourceNode)> | SourceNode | string): SourceNode;
setSourceContent(sourceFile: string, sourceContent: string): void;
walk(fn: (chunk: string, mapping: MappedPosition) => void): void;
walkSourceContents(fn: (file: string, content: string) => void): void;
join(sep: string): SourceNode;
replaceRight(pattern: string, replacement: string): SourceNode;
toString(): string;
toStringWithSourceMap(startOfSourceMap?: StartOfSourceMap): CodeWithSourceMap;
}

View file

@ -0,0 +1,8 @@
/*
* Copyright 2009-2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE.txt or:
* http://opensource.org/licenses/BSD-3-Clause
*/
exports.SourceMapGenerator = require("./lib/source-map-generator").SourceMapGenerator;
exports.SourceMapConsumer = require("./lib/source-map-consumer").SourceMapConsumer;
exports.SourceNode = require("./lib/source-node").SourceNode;

48
node_modules/v8-to-istanbul/package.json generated vendored Normal file
View file

@ -0,0 +1,48 @@
{
"name": "v8-to-istanbul",
"version": "7.1.2",
"description": "convert from v8 coverage format to istanbul's format",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"fix": "standard --fix",
"snapshot": "TAP_SNAPSHOT=1 tap test/*.js",
"test": "c8 --reporter=html --reporter=text tap --no-coverage --no-esm test/*.js",
"posttest": "standard",
"coverage": "c8 report --check-coverage"
},
"repository": "istanbuljs/v8-to-istanbul",
"keywords": [
"istanbul",
"v8",
"coverage"
],
"standard": {
"ignore": [
"**/test/fixtures"
]
},
"author": "Ben Coe <ben@npmjs.com>",
"license": "ISC",
"dependencies": {
"@types/istanbul-lib-coverage": "^2.0.1",
"convert-source-map": "^1.6.0",
"source-map": "^0.7.3"
},
"devDependencies": {
"@types/node": "^12.7.11",
"c8": "^7.2.1",
"semver": "^7.3.2",
"should": "13.2.3",
"standard": "^16.0.0",
"tap": "^14.10.8"
},
"engines": {
"node": ">=10.10.0"
},
"files": [
"lib/*.js",
"index.js",
"index.d.ts"
]
}