├── .gitignore
├── .npmignore
├── .travis.yml
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── README.md
├── bench
├── bench_decode.node.js
├── bench_decode_fast.node.js
├── index.html
├── scala.js.map
└── scalajs-runtime-sourcemap.js
├── bin
├── decode-source-map
└── encode-source-map
├── package.json
├── rollup.config.cli-decode.js
├── rollup.config.cli-encode.js
├── rollup.config.js
├── rollup.config.tests.js
├── src
├── base64.ts
├── cli
│ ├── decode-source-map.ts
│ └── encode-source-map.ts
├── concat.ts
├── decode.ts
├── decoder.ts
├── encode.ts
├── encoder.ts
├── index.ts
├── int-buffer-reader.ts
├── int-buffer-writer.ts
├── interfaces.ts
├── mapping-factories.ts
├── mappings-decoder.ts
├── mappings-encoder.ts
├── reader.ts
├── tests
│ ├── concat-tests.ts
│ ├── encoder-tests.ts
│ ├── fixtures
│ │ ├── map1-2.ts
│ │ ├── map1.ts
│ │ ├── map2.ts
│ │ ├── map3-4-1.ts
│ │ └── map3-4.ts
│ ├── index.ts
│ └── vlq-tests.ts
├── utils
│ ├── read-file.ts
│ ├── to-buffer.ts
│ └── to-string.ts
├── vlq.ts
└── writer.ts
├── tsconfig.json
├── tslint.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | /lib/
3 | /package/
4 | /dist/
5 | *.cfg
6 | *.asm
7 | *.tgz
8 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /src/
2 | /dist/tests/
3 | /lib/tests/
4 | /.vscode/
5 | /bench/
6 | /vendor/
7 | node_modules/
8 | /package/
9 | *.cfg
10 | *.asm
11 | *.tgz
12 | /.gitignore
13 | /.npmignore
14 | /rollup.*
15 | /tsconfig.json
16 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "8"
5 | - "6"
6 | - "4"
7 |
8 | install:
9 | - npm install
10 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Launch",
6 | "type": "node",
7 | "request": "launch",
8 | "program": "${workspaceRoot}/src/tests/index.ts",
9 | "stopOnEntry": false,
10 | "args": [],
11 | "cwd": "${workspaceRoot}",
12 | "preLaunchTask": "build",
13 | "runtimeExecutable": null,
14 | "runtimeArgs": [
15 | "--nolazy",
16 | "${workspaceRoot}/node_modules/.bin/_mocha"
17 | ],
18 | "env": {
19 | "NODE_ENV": "development"
20 | },
21 | "externalConsole": false,
22 | "sourceMaps": true,
23 | "outDir": "${workspaceRoot}/dist"
24 | }
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.exclude": {
3 | "**/.git": true,
4 | "**/node_modules": true
5 | },
6 | "search.exclude": {
7 | "dist/**": true,
8 | "**/node_modules": true,
9 | "**/vendor": true,
10 | "lib/**": true,
11 | "*.asm": true,
12 | "*.cfg": true
13 | },
14 | "typescript.tsdk": "./node_modules/typescript/lib",
15 | "json.schemas": [{
16 | "fileMatch": [
17 | "/tsconfig.json"
18 | ],
19 | "url": "http://json.schemastore.org/tsconfig?update"
20 | }]
21 | }
22 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "command": "npm",
4 | "isShellCommand": true,
5 | "args": ["run"],
6 | "tasks": [{
7 | "taskName": "build",
8 | "isBuildCommand": true,
9 | "showOutput": "always",
10 | "isWatching": false
11 | }]
12 | }
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fast Source Map [](https://travis-ci.org/krisselden/fast-source-map)
2 |
3 | Keeping the JIT gods happy since circa 2015
4 |
5 | When working with sourcemaps, VLQ encoding and decoding typically dominiates
6 | cost. To address this, this library provides a Fast VLQ encoder & decoder for
7 | JavaScript. By reducing allocations, minimizing transformations, and writing
8 | JIT friendly code we are able to drammatically improve performance.
9 |
10 | How much faster? At the time this README was written, decoding scala.js.map took:
11 |
12 | ```
13 | v8: 4.6.85.28
14 | node: 5.0.0
15 | os: 10.10.3
16 | hw: 2.5 GHz Intel Core i7, 16gb
17 | ```
18 |
19 | * source-map: ~5,000ms
20 | * fast-source-map ~ 500ms
21 |
22 | # Usage
23 |
24 | First we will need to have our `sourceMap.mappings` stored as a buffer. We have
25 | future plans to work directly on a sourceMap buffer, as that will allow for
26 | more ideal performance. Even without, the performance improvements are still
27 | well worth it.
28 |
29 | ```js
30 | var buffer = /* try to leave the map inert, and in buffer form. Otherwise convert to buffer */
31 | ```
32 |
33 | Typically, the following steps are required:
34 |
35 | Setup the reader
36 |
37 | The reader can read mappings from any array of ascii values.
38 | We will use Uint8Array in this example.
39 |
40 | ```js
41 | let map = JSON.parse(fs.readFileSync('path/to/source/to/decode.js.map', 'utf8'));
42 |
43 | let byteArray = new Uint8Array(map.mappings.length);
44 | let buffer = Buffer.from(byteArray.buffer);
45 | buffer.write(map.mappings, 0, 'ascii');
46 |
47 | const SM = require("fast-source-map");
48 | let reader = new SM.IntBufferReader(byteArray, 0, byteArray.length);
49 | ```
50 |
51 | Setup the decoder
52 |
53 | ```js
54 | let decoder = new SM.Decoder();
55 | let mappingsDecoder = new SM.MappingsDecoder(decoder);
56 | ```
57 |
58 | Now for some actual decoding
59 |
60 | ```js
61 | mappingsDecoder.decode(reader);
62 | decoder.mappings // => is the quickly decoded
63 | ```
64 |
65 | To concatenate multiple source maps
66 |
67 | ```js
68 | const decodeFile = SM.decodeFile;
69 |
70 | let concatenator = new SM.SourceMapConcatenator();
71 | concatenator.push(decodeFile('path/to/file-1.js.map'));
72 | concatenator.push(decodeFile('path/to/file-2.js.map'));
73 | concatenator.push(decodeFile('path/to/file-3.js.map'));
74 |
75 | concatenator.toJSON(); // => the concatenated source maps
76 | ```
77 |
78 | Now to reconcatenate the source maps after a source file is removed.
79 |
80 | ```js
81 | // file-2.js.map is removed
82 | concatenator.splice(1, 1);
83 | concatenator.toJSON(); // => the concatenated source maps
84 | ```
85 |
86 | And reconcatenate again after adding back other files.
87 |
88 | ```js
89 | // an updated file 2 and a new file 4 are added
90 | concatenator.splice(1, 0, decodeFile('path/to/file-2-updated.js.map'));
91 | concatenator.push(decodeFile('path/to/file-4.js.map'));
92 | concatenator.toJSON(); // => the concatenated source maps
93 | ```
94 |
--------------------------------------------------------------------------------
/bench/bench_decode.node.js:
--------------------------------------------------------------------------------
1 | var SourceMapConsumer = require('source-map').SourceMapConsumer;
2 | var fs = require('fs');
3 |
4 | function test() {
5 | var parsedSourceMap = JSON.parse(fs.readFileSync('bench/scala.js.map'));
6 |
7 | var start = Date.now();
8 | var sourceMapConsumer = new SourceMapConsumer(parsedSourceMap);
9 | sourceMapConsumer.eachMapping(function () {});
10 |
11 | return {
12 | decoded: sourceMapConsumer,
13 | duration: Date.now() - start,
14 | };
15 | }
16 |
17 | console.log('first run:', test().duration + 'ms'); // prime
18 | setTimeout(function() {
19 | console.log('second run:', test().duration + 'ms');
20 | });
21 |
--------------------------------------------------------------------------------
/bench/bench_decode_fast.node.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var decode = require('../dist/index').decode;
3 | var assert = require('assert');
4 |
5 | function test() {
6 | var parsed = JSON.parse(fs.readFileSync('bench/scala.js.map', 'utf8'));
7 | var start = Date.now();
8 | var decoded = decode(parsed);
9 |
10 | return {
11 | duration: Date.now() - start,
12 | decoded: decoded,
13 | }
14 | }
15 |
16 | console.log('first run:', test().duration + 'ms'); // warm up
17 |
18 | // let the world settle down
19 | setTimeout(function() {
20 | var result = test(); // actual test run
21 | var decoded = result.decoded;
22 | console.log('second run:', result.duration + 'ms'); // actual run
23 |
24 | // make sure the output appears reasonable
25 | assert(decoded.mappings.length === 379201, 'correct number of mappings')
26 | assert.deepEqual(decoded.mappings[0],
27 | [
28 | { fieldCount: 4, col: 0, src: 0, srcLine: 0, srcCol: 0, name: 0 },
29 | ],
30 | );
31 | assert.deepEqual(decoded.mappings[379200], []);
32 | }, 100);
33 |
--------------------------------------------------------------------------------
/bench/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/bin/decode-source-map:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | require('../dist/cli/decode-source-map');
3 |
--------------------------------------------------------------------------------
/bin/encode-source-map:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | require('../dist/cli/encode-source-map');
3 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fast-source-map",
3 | "version": "0.1.0",
4 | "description": "fast source mapping decode/encode",
5 | "main": "dist/index.js",
6 | "browser": "dist/browser.js",
7 | "jsnext:main": "lib/index.js",
8 | "typings": "lib/index.d.ts",
9 | "bin": {
10 | "decode-source-map": "./bin/decode-source-map",
11 | "encode-source-map": "./bin/encode-source-map"
12 | },
13 | "devDependencies": {
14 | "@types/chai": "^4.0.4",
15 | "@types/mocha": "^2.2.43",
16 | "@types/node": "^8.0.28",
17 | "chai": "^4.1.2",
18 | "mocha": "^3.5.3",
19 | "rollup": "^0.50.0",
20 | "sorcery": "^0.10.0",
21 | "source-map": "^0.5.6",
22 | "tslint": "^5.7.0",
23 | "typescript": "^2.5.2"
24 | },
25 | "scripts": {
26 | "build": "npm run build:typescript && npm run build:rollup && npm run build:rollup-tests && npm run build:rollup-cli-decode && npm run build:rollup-cli-encode",
27 | "build:typescript": "tsc",
28 | "build:rollup": "rollup -c rollup.config.js && sorcery -i dist/index.js && sorcery -i dist/browser.js",
29 | "build:rollup-tests": "rollup -c rollup.config.tests.js && sorcery -i dist/tests/index.js",
30 | "build:rollup-cli-decode": "rollup -c rollup.config.cli-decode.js && sorcery -i dist/cli/decode-source-map.js",
31 | "build:rollup-cli-encode": "rollup -c rollup.config.cli-encode.js && sorcery -i dist/cli/encode-source-map.js",
32 | "lint": "tslint src/**.ts",
33 | "prepublish": "npm run build",
34 | "pretest": "npm run lint",
35 | "test": "mocha dist/tests/index.js",
36 | "test:debug": "mocha debug dist/tests/index.js"
37 | },
38 | "keywords": [
39 | "source-map",
40 | "sourcemap",
41 | "decode",
42 | "encode",
43 | "vlq"
44 | ],
45 | "author": "Kris Selden ",
46 | "license": "MIT",
47 | "repository": {
48 | "type": "git",
49 | "url": "https://github.com/krisselden/fast-source-map.git"
50 | },
51 | "dependencies": {
52 | "concat-stream": "^1.5.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/rollup.config.cli-decode.js:
--------------------------------------------------------------------------------
1 | var DIST = __dirname + '/dist/index';
2 |
3 | var index = {
4 | resolveId: function (importee, importer) {
5 | if (importee === '../index') {
6 | return DIST;
7 | }
8 | // fallthrough
9 | }
10 | };
11 |
12 | export default {
13 | entry: 'lib/cli/decode-source-map.js',
14 | plugins: [index],
15 | format: 'cjs',
16 | dest: 'dist/cli/decode-source-map.js',
17 | sourceMap: 'dist/cli/decode-source-map.js.map',
18 | external: [DIST]
19 | };
20 |
--------------------------------------------------------------------------------
/rollup.config.cli-encode.js:
--------------------------------------------------------------------------------
1 | var DIST = __dirname + '/dist/index';
2 |
3 | var index = {
4 | resolveId: function (importee, importer) {
5 | if (importee === '../index') {
6 | return DIST;
7 | }
8 | // fallthrough
9 | }
10 | };
11 |
12 | export default {
13 | entry: 'lib/cli/encode-source-map.js',
14 | plugins: [index],
15 | format: 'cjs',
16 | dest: 'dist/cli/encode-source-map.js',
17 | sourceMap: 'dist/cli/encode-source-map.js.map',
18 | external: [DIST]
19 | };
20 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | entry: 'lib/index.js',
3 | targets: [
4 | {
5 | dest: 'dist/index.js',
6 | sourceMap: 'dist/index.js.map',
7 | format: 'cjs'
8 | },
9 | {
10 | dest: 'dist/browser.js',
11 | sourceMap: 'dist/browser.js.map',
12 | format: 'iife',
13 | moduleName: 'SM'
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/rollup.config.tests.js:
--------------------------------------------------------------------------------
1 | var DIST = __dirname + '/dist/index';
2 |
3 | var index = {
4 | resolveId: function (importee, importer) {
5 | if (importee === '../index') {
6 | return DIST;
7 | }
8 | // fallthrough
9 | }
10 | };
11 |
12 | export default {
13 | entry: 'lib/tests/index.js',
14 | plugins: [index],
15 | format: 'cjs',
16 | dest: 'dist/tests/index.js',
17 | sourceMap: 'dist/tests/index.js.map',
18 | external: ['chai', DIST],
19 | };
20 |
--------------------------------------------------------------------------------
/src/base64.ts:
--------------------------------------------------------------------------------
1 | export let uint6ToASCII = new Uint8Array(64);
2 | export let asciiToUint6 = new Uint8Array(127);
3 |
4 | const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
5 | for (let i = 0; i < 64; i++) {
6 | const ascii = chars.charCodeAt(i);
7 | uint6ToASCII[i] = ascii;
8 | asciiToUint6[ascii] = i;
9 | }
10 |
--------------------------------------------------------------------------------
/src/cli/decode-source-map.ts:
--------------------------------------------------------------------------------
1 | import { decode, decodeFile } from '../decode';
2 |
3 | const concat = require('concat-stream');
4 | const length = process.argv.length;
5 |
6 | if (length === 3) {
7 | console.log(JSON.stringify(decodeFile(process.argv[2])));
8 | } else if (length === 2) {
9 | process.stdin.pipe(concat((data: string) => {
10 | console.log(JSON.stringify(decode(JSON.parse(data))));
11 | }));
12 | } else {
13 | console.error('USAGE: decode FILE');
14 | process.exit(1);
15 | }
16 |
--------------------------------------------------------------------------------
/src/cli/encode-source-map.ts:
--------------------------------------------------------------------------------
1 | import { encode, encodeFile } from '../index';
2 |
3 | const concat = require('concat-stream');
4 | const length = process.argv.length;
5 |
6 | if (length === 3) {
7 | console.log(JSON.stringify(encodeFile(process.argv[2])));
8 | } else if (length === 2) {
9 | process.stdin.pipe(concat((data: string) => {
10 | console.log(JSON.stringify(encode(JSON.parse(data))));
11 | }));
12 | } else {
13 | console.error('USAGE: decode FILE');
14 | process.exit(1);
15 | }
16 |
--------------------------------------------------------------------------------
/src/concat.ts:
--------------------------------------------------------------------------------
1 | import { DecodedMappings, DecodedSourceMap } from './interfaces';
2 |
3 | /**
4 | * A function that concatenates source maps.
5 | *
6 | * Source maps are expected to be in the following format:
7 | *
8 | * ```js
9 | * {
10 | * version: ,
11 | * sources: [],
12 | * sourcesContent: [],
13 | * names: [],
14 | * mappings: [
15 | * [{
16 | * col: ,
17 | * src: ,
18 | * srcLine: ,
19 | * srcCol: ,
20 | * }]
21 | * ],
22 | * file:
23 | * }
24 | * ```
25 | */
26 | export default function concat(maps: DecodedSourceMap[]): DecodedSourceMap {
27 | const sources: string[] = maps.reduce((acc: string[], map: DecodedSourceMap) => {
28 | return acc.concat(map.sources);
29 | }, []);
30 | const sourcesContent = maps.reduce((acc: string[], map: DecodedSourceMap) => {
31 | return acc.concat(map.sourcesContent);
32 | }, []);
33 | const names = maps.reduce((acc: string[], map: DecodedSourceMap) => {
34 | return acc.concat(map.names);
35 | }, []);
36 |
37 | let srcOffset = 0;
38 | let nameOffset = 0;
39 | const mappings = maps.reduce((acc: DecodedMappings, map) => {
40 | acc = acc.concat(map.mappings.map((lineMappings) => {
41 | return lineMappings.map((mapping) => ({
42 | col: mapping.col,
43 | fieldCount: mapping.fieldCount,
44 | name: mapping.name + nameOffset,
45 | src: mapping.src + srcOffset,
46 | srcCol: mapping.srcCol,
47 | srcLine: mapping.srcLine,
48 | }));
49 | }));
50 |
51 | srcOffset += map.sources.length;
52 | nameOffset += map.names.length;
53 |
54 | return acc;
55 | }, []);
56 |
57 | return {
58 | file: '',
59 | mappings,
60 | names,
61 | sources,
62 | sourcesContent,
63 | version: '3',
64 | };
65 | }
66 |
--------------------------------------------------------------------------------
/src/decode.ts:
--------------------------------------------------------------------------------
1 | import Decoder from './decoder';
2 | import IntBufferReader from './int-buffer-reader';
3 | import { DecodedSourceMap } from './interfaces';
4 | import MappingsDecoder from './mappings-decoder';
5 | import readFile from './utils/read-file';
6 | import toBuffer from './utils/to-buffer';
7 |
8 | export function decode(map: any): DecodedSourceMap {
9 | const buffer = toBuffer(map.mappings);
10 | const reader = new IntBufferReader(buffer, 0, buffer.length);
11 | const decoder = new Decoder();
12 | const mappingsDecoder = new MappingsDecoder(decoder);
13 |
14 | mappingsDecoder.decode(reader);
15 |
16 | map.mappings = decoder.mappings;
17 |
18 | return map;
19 | }
20 |
21 | export function decodeFile(path: string) {
22 | return decode(JSON.parse(readFile(path)));
23 | }
24 |
--------------------------------------------------------------------------------
/src/decoder.ts:
--------------------------------------------------------------------------------
1 | import { DecodedMappings, LineMappings } from './interfaces';
2 | import { createMapping1, createMapping4, createMapping5 } from './mapping-factories';
3 | import { Delegate } from './mappings-decoder';
4 |
5 | export default class Decoder implements Delegate {
6 | public currentLine: LineMappings = [];
7 |
8 | public mappings: DecodedMappings = [this.currentLine];
9 |
10 | public newline() {
11 | this.currentLine = [];
12 | this.mappings.push(this.currentLine);
13 | }
14 |
15 | public mapping1(col: number) {
16 | this.currentLine.push(createMapping1(col));
17 | }
18 |
19 | public mapping4(col: number, src: number, srcLine: number, srcCol: number) {
20 | this.currentLine.push(createMapping4(col, src, srcLine, srcCol));
21 | }
22 |
23 | public mapping5(col: number, src: number, srcLine: number, srcCol: number, name: number) {
24 | this.currentLine.push(createMapping5(col, src, srcLine, srcCol, name));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/encode.ts:
--------------------------------------------------------------------------------
1 | import Encoder from './encoder';
2 | import IntBufferWriter from './int-buffer-writer';
3 | import MappingsEncoder from './mappings-encoder';
4 | import readFile from './utils/read-file';
5 | import toString from './utils/to-string';
6 |
7 | export function encode(map: any) {
8 | const buffer: number[] = [];
9 | const writer = new IntBufferWriter(buffer, 0);
10 | const encoder = new Encoder(writer);
11 | const mappingsEncoder = new MappingsEncoder(encoder);
12 |
13 | mappingsEncoder.encode(map.mappings);
14 |
15 | map.mappings = toString(buffer, 0, buffer.length);
16 |
17 | return map;
18 | }
19 |
20 | /**
21 | * Takes a source map file with a decoded `mappings` section and reencodes
22 | * `mappings`.
23 | */
24 | export function encodeFile(path: string) {
25 | const map = JSON.parse(readFile(path));
26 | return encode(map);
27 | }
28 |
--------------------------------------------------------------------------------
/src/encoder.ts:
--------------------------------------------------------------------------------
1 | import { Delegate } from './mappings-encoder';
2 | import { encodeVLQ } from './vlq';
3 | import Writer from './writer';
4 |
5 | export default class Encoder implements Delegate {
6 | public writer: Writer;
7 |
8 | constructor(writer: Writer) {
9 | this.writer = writer;
10 | }
11 |
12 | public separator() {
13 | this.writer.write(44); /* , */
14 | }
15 |
16 | public newline() {
17 | this.writer.write(59); /* ; */
18 | }
19 |
20 | public write5(column: number, source: number, sourceLine: number, sourceColumn: number, name: number) {
21 | encodeVLQ(this.writer, column);
22 | encodeVLQ(this.writer, source);
23 | encodeVLQ(this.writer, sourceLine);
24 | encodeVLQ(this.writer, sourceColumn);
25 | encodeVLQ(this.writer, name);
26 | }
27 |
28 | public write4(column: number, source: number, sourceLine: number, sourceColumn: number) {
29 | encodeVLQ(this.writer, column);
30 | encodeVLQ(this.writer, source);
31 | encodeVLQ(this.writer, sourceLine);
32 | encodeVLQ(this.writer, sourceColumn);
33 | }
34 |
35 | public write1(column: number) {
36 | encodeVLQ(this.writer, column);
37 | }
38 |
39 | get length() {
40 | return this.writer.length;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { encodeVLQ, decodeVLQ } from './vlq';
2 | export { default as IntBufferReader } from './int-buffer-reader';
3 | export { default as IntBufferWriter } from './int-buffer-writer';
4 | export { default as MappingsEncoder, Delegate as MappingsEncoderDelegate } from './mappings-encoder';
5 | export { default as MappingsDecoder, Delegate as MappingsDecoderDelegate } from './mappings-decoder';
6 | export { default as Encoder } from './encoder';
7 | export { default as Decoder } from './decoder';
8 | export { default as concat } from './concat';
9 | export { decode, decodeFile } from './decode';
10 | export { encode, encodeFile } from './encode';
11 |
--------------------------------------------------------------------------------
/src/int-buffer-reader.ts:
--------------------------------------------------------------------------------
1 | import Reader from './reader';
2 |
3 | export default class IntBufferReader implements Reader {
4 | public buf: number[] | Uint8Array;
5 | public ptr: number;
6 | public limit: number;
7 |
8 | constructor(buf: number[] | Uint8Array, ptr: number, len: number) {
9 | this.buf = buf;
10 | this.ptr = ptr | 0;
11 | this.limit = (ptr + len) | 0;
12 | }
13 |
14 | public peek() {
15 | return this.buf[this.ptr | 0] | 0;
16 | }
17 |
18 | public read() {
19 | const n = this.buf[this.ptr | 0] | 0;
20 | this.ptr = (this.ptr + 1) | 0;
21 | return n;
22 | }
23 |
24 | public next() {
25 | this.ptr = (this.ptr + 1) | 0;
26 | }
27 |
28 | public hasNext(): boolean {
29 | return this.ptr < this.limit;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/int-buffer-writer.ts:
--------------------------------------------------------------------------------
1 | import Writer from './writer';
2 |
3 | export default class IntBufferWriter implements Writer {
4 | public buf: number[] | Uint8Array;
5 | public ptr: number;
6 |
7 | constructor(buf: number[] | Uint8Array, ptr: number) {
8 | this.buf = buf;
9 | this.ptr = ptr | 0;
10 | }
11 |
12 | public write(n: number) {
13 | this.buf[this.ptr++] = n | 0;
14 | }
15 |
16 | public get length() {
17 | return this.buf.length;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/interfaces.ts:
--------------------------------------------------------------------------------
1 | export interface DecodedMapping {
2 | fieldCount: number;
3 | col: number;
4 | src: number;
5 | srcLine: number;
6 | srcCol: number;
7 | name: number;
8 | }
9 |
10 | export type LineMappings = DecodedMapping[];
11 |
12 | export type DecodedMappings = LineMappings[];
13 |
14 | export interface DecodedSourceMap {
15 | version: string;
16 | sources: string[];
17 | sourcesContent: string[];
18 | names: string[];
19 | mappings: DecodedMappings;
20 | file: string;
21 | }
22 |
--------------------------------------------------------------------------------
/src/mapping-factories.ts:
--------------------------------------------------------------------------------
1 | import { DecodedMapping } from './interfaces';
2 |
3 | export function createMapping1(col: number): DecodedMapping {
4 | return {
5 | col,
6 | fieldCount: 1,
7 | name: 0,
8 | src: 0,
9 | srcCol: 0,
10 | srcLine: 0,
11 | };
12 | }
13 |
14 | export function createMapping4(col: number, src: number, srcLine: number, srcCol: number): DecodedMapping {
15 | return {
16 | col,
17 | fieldCount: 4,
18 | name: 0,
19 | src,
20 | srcCol,
21 | srcLine,
22 | };
23 | }
24 |
25 | export function createMapping5(col: number,
26 | src: number,
27 | srcLine: number,
28 | srcCol: number,
29 | name: number): DecodedMapping {
30 | return {
31 | col,
32 | fieldCount: 5,
33 | name,
34 | src,
35 | srcCol,
36 | srcLine,
37 | };
38 | }
39 |
--------------------------------------------------------------------------------
/src/mappings-decoder.ts:
--------------------------------------------------------------------------------
1 | import Reader from './reader';
2 | import { decodeVLQ } from './vlq';
3 |
4 | export interface Delegate {
5 | newline(): void;
6 | mapping1(column: number): void;
7 | mapping4(column: number, source: number, sourceLine: number, sourceColumn: number): void;
8 | mapping5(column: number, source: number, sourceLine: number, sourceColumn: number, name: number): void;
9 | }
10 |
11 | export default class MappingsDecoder {
12 | // absolutes
13 | public line = 0;
14 | public column = 0;
15 | public source = 0;
16 | public sourceLine = 0;
17 | public sourceColumn = 0;
18 | public name = 0;
19 |
20 | public fieldCount = 0;
21 |
22 | public delegate: Delegate;
23 |
24 | constructor(delegate: Delegate) {
25 | this.delegate = delegate;
26 | }
27 |
28 | public decode(reader: Reader) {
29 | while (reader.hasNext()) {
30 | switch (reader.peek()) {
31 | case 59: // semicolon
32 | if (this.fieldCount > 0) {
33 | this.emitMapping();
34 | }
35 | this.emitNewline();
36 | this.column = 0;
37 | this.fieldCount = 0;
38 | reader.next();
39 | break;
40 | case 44: // comma
41 | this.emitMapping();
42 | this.fieldCount = 0;
43 | reader.next();
44 | break;
45 | default:
46 | this.decodeField(reader);
47 | break;
48 | }
49 | }
50 | if (this.fieldCount > 0) {
51 | this.emitMapping();
52 | }
53 | }
54 |
55 | public emitNewline() {
56 | this.delegate.newline();
57 | }
58 |
59 | public emitMapping() {
60 | switch (this.fieldCount) {
61 | case 1:
62 | this.delegate.mapping1(this.column);
63 | break;
64 | case 4:
65 | this.delegate.mapping4(this.column, this.source, this.sourceLine, this.sourceColumn);
66 | break;
67 | case 5:
68 | this.delegate.mapping5(this.column, this.source, this.sourceLine, this.sourceColumn, this.name);
69 | break;
70 | }
71 | }
72 |
73 | public decodeField(reader: Reader) {
74 | const value = decodeVLQ(reader) | 0;
75 | switch (this.fieldCount) {
76 | case 0:
77 | this.column += value;
78 | this.fieldCount = 1;
79 | break;
80 | case 1:
81 | this.source += value;
82 | this.fieldCount = 2;
83 | break;
84 | case 2:
85 | this.sourceLine += value;
86 | this.fieldCount = 3;
87 | break;
88 | case 3:
89 | this.sourceColumn += value;
90 | this.fieldCount = 4;
91 | break;
92 | case 4:
93 | this.name += value;
94 | this.fieldCount = 5;
95 | break;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/mappings-encoder.ts:
--------------------------------------------------------------------------------
1 | import { DecodedMappings } from './interfaces';
2 |
3 | export interface Delegate {
4 | length: number;
5 | newline(): void;
6 | separator(): void;
7 | write1(column: number): void;
8 | write4(column: number, source: number, sourceLine: number, sourceColumn: number): void;
9 | write5(column: number, source: number, sourceLine: number, sourceColumn: number, name: number): void;
10 | }
11 |
12 | export default class MappingsEncoder {
13 | public column = 0;
14 | public source = 0;
15 | public sourceLine = 0;
16 | public sourceColumn = 0;
17 | public name = 0;
18 |
19 | public delegate: Delegate;
20 |
21 | constructor(delegate: Delegate) {
22 | this.delegate = delegate;
23 | }
24 |
25 | public encode(mappings: DecodedMappings) {
26 | for (let i = 0; i < mappings.length; i++) {
27 | const line = mappings[i];
28 |
29 | for (let j = 0; j < line.length; j++) {
30 | const mapping = line[j];
31 |
32 | switch (mapping.fieldCount) {
33 | case 1:
34 | this.write1(mapping);
35 | break;
36 | case 4:
37 | this.write4(mapping);
38 | break;
39 | case 5:
40 | this.write5(mapping);
41 | break;
42 | default:
43 | missingFieldCount();
44 | }
45 |
46 | if (j < line.length - 1) {
47 | // no trailing segment separator
48 | this.separator();
49 | }
50 | }
51 |
52 | if (i < mappings.length - 1 ) {
53 | // skip trailing line separator
54 | this.newline();
55 | }
56 |
57 | this.column = 0;
58 | }
59 |
60 | return this.delegate.length;
61 | }
62 |
63 | public separator() {
64 | this.delegate.separator();
65 | }
66 |
67 | public newline() {
68 | this.delegate.newline();
69 | }
70 |
71 | public write5(mapping: {
72 | col: number;
73 | src: number;
74 | srcLine: number;
75 | srcCol: number;
76 | name: number;
77 | }) {
78 | this.delegate.write5(
79 | mapping.col - this.column,
80 | mapping.src - this.source,
81 | mapping.srcLine - this.sourceLine,
82 | mapping.srcCol - this.sourceColumn,
83 | mapping.name - this.name);
84 |
85 | this.column = mapping.col;
86 | this.source = mapping.src;
87 | this.sourceLine = mapping.srcLine;
88 | this.sourceColumn = mapping.srcCol;
89 | this.name = mapping.name;
90 | }
91 |
92 | public write4(mapping: {
93 | col: number;
94 | src: number;
95 | srcLine: number;
96 | srcCol: number;
97 | }) {
98 | this.delegate.write4(
99 | mapping.col - this.column,
100 | mapping.src - this.source,
101 | mapping.srcLine - this.sourceLine,
102 | mapping.srcCol - this.sourceColumn);
103 |
104 | this.column = mapping.col;
105 | this.source = mapping.src;
106 | this.sourceLine = mapping.srcLine;
107 | this.sourceColumn = mapping.srcCol;
108 | }
109 |
110 | public write1(mapping: {
111 | col: number;
112 | }) {
113 | this.delegate.write1(mapping.col - this.column);
114 |
115 | this.column = mapping.col;
116 | }
117 | }
118 |
119 | function missingFieldCount() {
120 | throw new TypeError('mappings to encode require fieldCount');
121 | }
122 |
--------------------------------------------------------------------------------
/src/reader.ts:
--------------------------------------------------------------------------------
1 | interface Reader {
2 | /**
3 | * Returns the next byte without moving the pointer.
4 | */
5 | peek(): number;
6 |
7 | /**
8 | * Returns the next byte and moves the pointer forward.
9 | */
10 | read(): number;
11 |
12 | /**
13 | * Moves the pointer forward without reading any bytes.
14 | */
15 | next(): void;
16 |
17 | /**
18 | * Returns whether the pointer has reached the end of the buffer.
19 | */
20 | hasNext(): boolean;
21 | }
22 |
23 | export default Reader;
24 |
--------------------------------------------------------------------------------
/src/tests/concat-tests.ts:
--------------------------------------------------------------------------------
1 | import { concat } from '../index';
2 |
3 | import { expect } from 'chai';
4 | import map1 from './fixtures/map1';
5 | import map1_2 from './fixtures/map1-2';
6 | import map2 from './fixtures/map2';
7 | import map3_4 from './fixtures/map3-4';
8 | import map3_4_1 from './fixtures/map3-4-1';
9 |
10 | describe('concat()', () => {
11 | it('can output an empty source map', () => {
12 | expect(concat([])).to.deep.equal({
13 | file: '',
14 | mappings: [],
15 | names: [],
16 | sources: [],
17 | sourcesContent: [],
18 | version: '3',
19 | }, 'concatenator can output the empty case');
20 | });
21 |
22 | it('can output a single source map', () => {
23 | const map = {
24 | file: 'map1.js',
25 | mappings: [[{
26 | col: 0,
27 | fieldCount: 4,
28 | name: 0,
29 | src: 0,
30 | srcCol: 0,
31 | srcLine: 1,
32 | }]],
33 | names: [] as string[],
34 | sources: [ 'file1.js' ],
35 | sourcesContent: [] as string[],
36 | version: '3',
37 | };
38 |
39 | expect(concat([map])).to.deep.equal({
40 | file: '',
41 | mappings: [[{
42 | col: 0,
43 | fieldCount: 4,
44 | src: 0,
45 | srcCol: 0,
46 | srcLine: 1,
47 | }]],
48 | names: [],
49 | sources: [ 'file1.js' ],
50 | sourcesContent: [],
51 | version: '3',
52 | }, 'concatenator can output a single source map');
53 | });
54 |
55 | it('can produce simple merged source maps', () => {
56 | expect(concat([map1, map2])).to.deep.equal(map1_2);
57 | });
58 |
59 | it('can merge source maps with multiple sources', () => {
60 | expect(concat([map3_4, map1])).to.deep.equal(map3_4_1);
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/src/tests/encoder-tests.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import { MappingsEncoder, MappingsEncoderDelegate } from '../index';
3 |
4 | class Encoder implements MappingsEncoderDelegate {
5 | public writes: Array = [];
6 |
7 | public write1(n: number): void {
8 | this.writes.push(n);
9 | }
10 |
11 | public write4(a: number, b: number, c: number, d: number): void {
12 | this.writes.push(a, b, c, d);
13 | }
14 |
15 | public write5(a: number, b: number, c: number, d: number, e: number): void {
16 | this.writes.push(a, b, c, d, e);
17 | }
18 |
19 | public separator(): void {
20 | this.writes.push(',');
21 | }
22 |
23 | public newline(): void {
24 | this.writes.push(';');
25 | }
26 |
27 | get length(): number {
28 | return this.writes.length;
29 | }
30 | }
31 |
32 | describe('Encoder', () => {
33 | let encoder: Encoder;
34 | let mapper: MappingsEncoder;
35 | let mapping: { col: number, src: number, srcLine: number, srcCol: number, name: number };
36 |
37 | beforeEach( () => {
38 | encoder = new Encoder();
39 | mapper = new MappingsEncoder(encoder);
40 |
41 | mapping = {
42 | col: 197,
43 | name: 2,
44 | src: 0,
45 | srcCol: 29,
46 | srcLine: 7,
47 | };
48 | });
49 |
50 | describe('write1', () => {
51 | it('writes the `col` field', () => {
52 | expect(encoder.writes).to.deep.equal([]);
53 |
54 | mapper.write1(mapping);
55 |
56 | expect(encoder.writes).to.deep.equal([ 197 ]);
57 | });
58 | });
59 |
60 | describe('write4', () => {
61 | it('writes the col, src, srcLine and srcCol fields in order', () => {
62 | expect(encoder.writes).to.deep.equal([]);
63 |
64 | mapper.write4(mapping);
65 |
66 | expect(encoder.writes).to.deep.equal([ 197, 0, 7, 29 ]);
67 | });
68 | });
69 |
70 | describe('write5', () => {
71 | it('writes the col, src, srcLine, srcCol and name fields in order', () => {
72 | expect(encoder.writes).to.deep.equal([]);
73 |
74 | mapper.write5(mapping);
75 |
76 | expect(encoder.writes).to.deep.equal([ 197, 0, 7, 29, 2 ]);
77 | });
78 | });
79 |
80 | describe('encode', () => {
81 | it('encodes sequences of the same field length', () => {
82 | expect(encoder.writes).to.deep.equal([]);
83 |
84 | mapper.encode([[{
85 | col: 105,
86 | fieldCount: 1,
87 | name: 0,
88 | src: 0,
89 | srcCol: 0,
90 | srcLine: 0,
91 | }, {
92 | col: 200,
93 | fieldCount: 1,
94 | name: 0,
95 | src: 0,
96 | srcCol: 0,
97 | srcLine: 0,
98 | }, {
99 | col: 300,
100 | fieldCount: 1,
101 | name: 0,
102 | src: 0,
103 | srcCol: 0,
104 | srcLine: 0,
105 | }]]);
106 |
107 | expect(encoder.writes).to.deep.equal([ 105, ',', 95, ',', 100 ]);
108 | });
109 |
110 | it('encodes sequences of mixed field lengths', () => {
111 | expect(encoder.writes).to.deep.equal([]);
112 |
113 | mapper.encode([[{
114 | col: 10,
115 | fieldCount: 5,
116 | name: 14,
117 | src: 11,
118 | srcCol: 13,
119 | srcLine: 12,
120 | }, {
121 | col: 20,
122 | fieldCount: 1,
123 | name: 0,
124 | src: 0,
125 | srcCol: 0,
126 | srcLine: 0,
127 | }, {
128 | col: 30,
129 | fieldCount: 4,
130 | name: 0,
131 | src: 31,
132 | srcCol: 33,
133 | srcLine: 32,
134 | }]]);
135 |
136 | expect(encoder.writes).to.deep.equal([
137 | 10, 11, 12, 13, 14, ',',
138 | 10, ',',
139 | 10, 20, 20, 20,
140 | ]);
141 | });
142 |
143 | it('encodes multiple lines with single segments', () => {
144 | expect(encoder.writes).to.deep.equal([]);
145 |
146 | mapper.encode([[
147 | {
148 | col: 10,
149 | fieldCount: 1,
150 | name: 0,
151 | src: 0,
152 | srcCol: 0,
153 | srcLine: 0,
154 | }, {
155 | col: 20,
156 | fieldCount: 1,
157 | name: 0,
158 | src: 0,
159 | srcCol: 0,
160 | srcLine: 0,
161 | },
162 | ], [
163 | {
164 | col: 100,
165 | fieldCount: 1,
166 | name: 0,
167 | src: 0,
168 | srcCol: 0,
169 | srcLine: 0,
170 | },
171 | ]]);
172 |
173 | expect(encoder.writes).to.deep.equal([
174 | 10, ',', 10, ';',
175 | 100,
176 | ]);
177 | });
178 |
179 | it('encodes multiple lines with multiple mixed segments', () => {
180 | expect(encoder.writes).to.deep.equal([]);
181 |
182 | mapper.encode([[
183 | {
184 | col: 10,
185 | fieldCount: 1,
186 | name: 0,
187 | src: 0,
188 | srcCol: 0,
189 | srcLine: 0,
190 | }, {
191 | col: 20,
192 | fieldCount: 1,
193 | name: 0,
194 | src: 0,
195 | srcCol: 0,
196 | srcLine: 0,
197 | },
198 | ], [
199 | {
200 | col: 100,
201 | fieldCount: 5,
202 | name: 104,
203 | src: 101,
204 | srcCol: 103,
205 | srcLine: 102,
206 | },
207 | ], [
208 | {
209 | col: 200,
210 | fieldCount: 4,
211 | name: 0,
212 | src: 201,
213 | srcCol: 203,
214 | srcLine: 202,
215 | }, {
216 | col: 300,
217 | fieldCount: 4,
218 | name: 0,
219 | src: 301,
220 | srcCol: 303,
221 | srcLine: 302,
222 | },
223 | ]]);
224 |
225 | expect(encoder.writes).to.deep.equal([
226 | 10, ',', 10, ';',
227 | 100, 101, 102, 103, 104, ';',
228 | 200, 100, 100, 100, ',', 100, 100, 100, 100,
229 | ]);
230 | });
231 | });
232 | });
233 |
--------------------------------------------------------------------------------
/src/tests/fixtures/map1-2.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | file: '',
3 | mappings: [
4 | // first.js mappings
5 | [
6 | {
7 | col: 0,
8 | fieldCount: 4,
9 | name: 0,
10 | src: 0,
11 | srcCol: 0,
12 | srcLine: 0,
13 | },
14 | ],
15 | [
16 | {
17 | col: 0,
18 | fieldCount: 4,
19 | name: 0,
20 | src: 0,
21 | srcCol: 0,
22 | srcLine: 1,
23 | },
24 | ],
25 | [
26 | {
27 | col: 0,
28 | fieldCount: 4,
29 | name: 0,
30 | src: 0,
31 | srcCol: 0,
32 | srcLine: 2,
33 | },
34 | ],
35 | [
36 | {
37 | col: 0,
38 | fieldCount: 4,
39 | name: 0,
40 | src: 0,
41 | srcCol: 0,
42 | srcLine: 3,
43 | },
44 | ],
45 | [
46 | {
47 | col: 0,
48 | fieldCount: 4,
49 | name: 0,
50 | src: 0,
51 | srcCol: 0,
52 | srcLine: 4,
53 | },
54 | ],
55 | [
56 | {
57 | col: 0,
58 | fieldCount: 4,
59 | name: 0,
60 | src: 0,
61 | srcCol: 0,
62 | srcLine: 5,
63 | },
64 | ],
65 | [
66 | {
67 | col: 0,
68 | fieldCount: 4,
69 | name: 0,
70 | src: 0,
71 | srcCol: 0,
72 | srcLine: 6,
73 | },
74 | ],
75 | // second.js mappings
76 | [
77 | {
78 | col: 0,
79 | fieldCount: 4,
80 | name: 0,
81 | src: 1,
82 | srcCol: 0,
83 | srcLine: 0,
84 | },
85 | ],
86 | [
87 | {
88 | col: 0,
89 | fieldCount: 4,
90 | name: 0,
91 | src: 1,
92 | srcCol: 0,
93 | srcLine: 1,
94 | },
95 | ],
96 | [
97 | {
98 | col: 0,
99 | fieldCount: 4,
100 | name: 0,
101 | src: 1,
102 | srcCol: 0,
103 | srcLine: 2,
104 | },
105 | ],
106 | ],
107 | names: [] as string[],
108 | sources: [
109 | 'test/fixtures/inner/first.js',
110 | 'test/fixtures/inner/second.js',
111 | ],
112 | sourcesContent: [
113 | 'function meaningOfLife() {\n throw new Error(42);\n}\n\nfunction boom() {\n throw new Error(\'boom\');\n}\n',
114 | 'function somethingElse() {\n throw new Error("somethign else");\n}\n',
115 | ],
116 | version: '3',
117 | };
118 |
--------------------------------------------------------------------------------
/src/tests/fixtures/map1.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | file: 'map1.js',
3 | mappings: [
4 | [
5 | {
6 | col: 0,
7 | fieldCount: 4,
8 | name: 0,
9 | src: 0,
10 | srcCol: 0,
11 | srcLine: 0,
12 | },
13 | ],
14 | [
15 | {
16 | col: 0,
17 | fieldCount: 4,
18 | name: 0,
19 | src: 0,
20 | srcCol: 0,
21 | srcLine: 1,
22 | },
23 | ],
24 | [
25 | {
26 | col: 0,
27 | fieldCount: 4,
28 | name: 0,
29 | src: 0,
30 | srcCol: 0,
31 | srcLine: 2,
32 | },
33 | ],
34 | [
35 | {
36 | col: 0,
37 | fieldCount: 4,
38 | name: 0,
39 | src: 0,
40 | srcCol: 0,
41 | srcLine: 3,
42 | },
43 | ],
44 | [
45 | {
46 | col: 0,
47 | fieldCount: 4,
48 | name: 0,
49 | src: 0,
50 | srcCol: 0,
51 | srcLine: 4,
52 | },
53 | ],
54 | [
55 | {
56 | col: 0,
57 | fieldCount: 4,
58 | name: 0,
59 | src: 0,
60 | srcCol: 0,
61 | srcLine: 5,
62 | },
63 | ],
64 | [
65 | {
66 | col: 0,
67 | fieldCount: 4,
68 | name: 0,
69 | src: 0,
70 | srcCol: 0,
71 | srcLine: 6,
72 | },
73 | ],
74 | ],
75 | names: [],
76 | sources: [ 'test/fixtures/inner/first.js' ],
77 | sourcesContent: [
78 | 'function meaningOfLife() {\n throw new Error(42);\n}\n\nfunction boom() {\n throw new Error(\'boom\');\n}\n',
79 | ],
80 | version: '3',
81 | };
82 |
--------------------------------------------------------------------------------
/src/tests/fixtures/map2.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | file: 'map2.js',
3 | mappings: [
4 | [
5 | {
6 | col: 0,
7 | fieldCount: 4,
8 | name: 0,
9 | src: 0,
10 | srcCol: 0,
11 | srcLine: 0,
12 | },
13 | ],
14 | [
15 | {
16 | col: 0,
17 | fieldCount: 4,
18 | name: 0,
19 | src: 0,
20 | srcCol: 0,
21 | srcLine: 1,
22 | },
23 | ],
24 | [
25 | {
26 | col: 0,
27 | fieldCount: 4,
28 | name: 0,
29 | src: 0,
30 | srcCol: 0,
31 | srcLine: 2,
32 | },
33 | ],
34 | ],
35 | names: [],
36 | sources: [
37 | 'test/fixtures/inner/second.js',
38 | ],
39 | sourcesContent: [
40 | 'function somethingElse() {\n throw new Error("somethign else");\n}\n',
41 | ],
42 | version: '3',
43 | };
44 |
--------------------------------------------------------------------------------
/src/tests/fixtures/map3-4-1.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | file: '',
3 | mappings: [
4 | // third.js mappings
5 | [
6 | {
7 | col: 0,
8 | fieldCount: 4,
9 | name: 0,
10 | src: 0,
11 | srcCol: 0,
12 | srcLine: 0,
13 | },
14 | ],
15 | [
16 | {
17 | col: 0,
18 | fieldCount: 4,
19 | name: 0,
20 | src: 0,
21 | srcCol: 0,
22 | srcLine: 1,
23 | },
24 | ],
25 | [
26 | {
27 | col: 0,
28 | fieldCount: 4,
29 | name: 0,
30 | src: 0,
31 | srcCol: 0,
32 | srcLine: 2,
33 | },
34 | ],
35 | [
36 | {
37 | col: 0,
38 | fieldCount: 4,
39 | name: 0,
40 | src: 0,
41 | srcCol: 0,
42 | srcLine: 3,
43 | },
44 | ],
45 | [
46 | {
47 | col: 0,
48 | fieldCount: 4,
49 | name: 0,
50 | src: 0,
51 | srcCol: 0,
52 | srcLine: 4,
53 | },
54 | ],
55 | [
56 | {
57 | col: 0,
58 | fieldCount: 4,
59 | name: 0,
60 | src: 0,
61 | srcCol: 0,
62 | srcLine: 5,
63 | },
64 | ],
65 | [
66 | {
67 | col: 0,
68 | fieldCount: 4,
69 | name: 0,
70 | src: 0,
71 | srcCol: 0,
72 | srcLine: 6,
73 | },
74 | ],
75 | // fourth.js mappings
76 | [
77 | {
78 | col: 0,
79 | fieldCount: 4,
80 | name: 0,
81 | src: 1,
82 | srcCol: 0,
83 | srcLine: 0,
84 | },
85 | ],
86 | [
87 | {
88 | col: 0,
89 | fieldCount: 4,
90 | name: 0,
91 | src: 1,
92 | srcCol: 0,
93 | srcLine: 1,
94 | },
95 | ],
96 | [
97 | {
98 | col: 0,
99 | fieldCount: 4,
100 | name: 0,
101 | src: 1,
102 | srcCol: 0,
103 | srcLine: 2,
104 | },
105 | ],
106 | // first.js mappings
107 | [
108 | {
109 | col: 0,
110 | fieldCount: 4,
111 | name: 0,
112 | src: 2,
113 | srcCol: 0,
114 | srcLine: 0,
115 | },
116 | ],
117 | [
118 | {
119 | col: 0,
120 | fieldCount: 4,
121 | name: 0,
122 | src: 2,
123 | srcCol: 0,
124 | srcLine: 1,
125 | },
126 | ],
127 | [
128 | {
129 | col: 0,
130 | fieldCount: 4,
131 | name: 0,
132 | src: 2,
133 | srcCol: 0,
134 | srcLine: 2,
135 | },
136 | ],
137 | [
138 | {
139 | col: 0,
140 | fieldCount: 4,
141 | name: 0,
142 | src: 2,
143 | srcCol: 0,
144 | srcLine: 3,
145 | },
146 | ],
147 | [
148 | {
149 | col: 0,
150 | fieldCount: 4,
151 | name: 0,
152 | src: 2,
153 | srcCol: 0,
154 | srcLine: 4,
155 | },
156 | ],
157 | [
158 | {
159 | col: 0,
160 | fieldCount: 4,
161 | name: 0,
162 | src: 2,
163 | srcCol: 0,
164 | srcLine: 5,
165 | },
166 | ],
167 | [
168 | {
169 | col: 0,
170 | fieldCount: 4,
171 | name: 0,
172 | src: 2,
173 | srcCol: 0,
174 | srcLine: 6,
175 | },
176 | ],
177 | ],
178 | names: [],
179 | sources: [
180 | 'test/fixtures/inner/third.js',
181 | 'test/fixtures/inner/fourth.js',
182 | 'test/fixtures/inner/first.js',
183 | ],
184 | sourcesContent: [
185 | 'function meaningOfLife() {\n throw new Error(42);\n}\n\nfunction boom() {\n throw new Error(\'boom\');\n}\n',
186 | 'function somethingElse() {\n throw new Error("somethign else");\n}\n',
187 | 'function meaningOfLife() {\n throw new Error(42);\n}\n\nfunction boom() {\n throw new Error(\'boom\');\n}\n',
188 | ],
189 | version: '3',
190 | };
191 |
--------------------------------------------------------------------------------
/src/tests/fixtures/map3-4.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | file: '',
3 | mappings: [
4 | // third.js mappings
5 | [
6 | {
7 | col: 0,
8 | fieldCount: 4,
9 | name: 0,
10 | src: 0,
11 | srcCol: 0,
12 | srcLine: 0,
13 | },
14 | ],
15 | [
16 | {
17 | col: 0,
18 | fieldCount: 4,
19 | name: 0,
20 | src: 0,
21 | srcCol: 0,
22 | srcLine: 1,
23 | },
24 | ],
25 | [
26 | {
27 | col: 0,
28 | fieldCount: 4,
29 | name: 0,
30 | src: 0,
31 | srcCol: 0,
32 | srcLine: 2,
33 | },
34 | ],
35 | [
36 | {
37 | col: 0,
38 | fieldCount: 4,
39 | name: 0,
40 | src: 0,
41 | srcCol: 0,
42 | srcLine: 3,
43 | },
44 | ],
45 | [
46 | {
47 | col: 0,
48 | fieldCount: 4,
49 | name: 0,
50 | src: 0,
51 | srcCol: 0,
52 | srcLine: 4,
53 | },
54 | ],
55 | [
56 | {
57 | col: 0,
58 | fieldCount: 4,
59 | name: 0,
60 | src: 0,
61 | srcCol: 0,
62 | srcLine: 5,
63 | },
64 | ],
65 | [
66 | {
67 | col: 0,
68 | fieldCount: 4,
69 | name: 0,
70 | src: 0,
71 | srcCol: 0,
72 | srcLine: 6,
73 | },
74 | ],
75 | // fourth.js mappings
76 | [
77 | {
78 | col: 0,
79 | fieldCount: 4,
80 | name: 0,
81 | src: 1,
82 | srcCol: 0,
83 | srcLine: 0,
84 | },
85 | ],
86 | [
87 | {
88 | col: 0,
89 | fieldCount: 4,
90 | name: 0,
91 | src: 1,
92 | srcCol: 0,
93 | srcLine: 1,
94 | },
95 | ],
96 | [
97 | {
98 | col: 0,
99 | fieldCount: 4,
100 | name: 0,
101 | src: 1,
102 | srcCol: 0,
103 | srcLine: 2,
104 | },
105 | ],
106 | ],
107 | names: [],
108 | sources: [
109 | 'test/fixtures/inner/third.js',
110 | 'test/fixtures/inner/fourth.js',
111 | ],
112 | sourcesContent: [
113 | 'function meaningOfLife() {\n throw new Error(42);\n}\n\nfunction boom() {\n throw new Error(\'boom\');\n}\n',
114 | 'function somethingElse() {\n throw new Error("somethign else");\n}\n',
115 | ],
116 | version: '3',
117 | };
118 |
--------------------------------------------------------------------------------
/src/tests/index.ts:
--------------------------------------------------------------------------------
1 | export * from './concat-tests';
2 | export * from './encoder-tests';
3 | export * from './vlq-tests';
4 |
--------------------------------------------------------------------------------
/src/tests/vlq-tests.ts:
--------------------------------------------------------------------------------
1 | import toBuffer from '../utils/to-buffer';
2 | import toString from '../utils/to-string';
3 |
4 | import {
5 | Decoder,
6 | decodeVLQ,
7 | Encoder,
8 | encodeVLQ,
9 | IntBufferReader,
10 | IntBufferWriter,
11 | MappingsDecoder,
12 | MappingsEncoder,
13 | } from '../index';
14 |
15 | import { expect } from 'chai';
16 |
17 | describe('test encode', () => {
18 | it('encodeVLQ', () => {
19 | let writer = new IntBufferWriter([], 0);
20 |
21 | [ 123, 456, 789, 987, 654, 321 ].forEach((n) => {
22 | encodeVLQ(writer, n);
23 | });
24 |
25 | expect(toString(writer.buf, 0, writer.ptr)).to.equal('2HwcqxB29B8oBiU');
26 |
27 | writer = new IntBufferWriter(new Int32Array(10), 0);
28 |
29 | [ -1, 2, 1, 7, -1, 2, 6, 2 ].forEach((n) => {
30 | encodeVLQ(writer, n);
31 | });
32 | expect(toString(writer.buf, 0, writer.ptr)).to.equal('DECODEME');
33 | });
34 |
35 | it('decodeVLQ', () => {
36 | // tslint:disable-next-line:max-line-length
37 | const output = {
38 | buf: new Int32Array(10),
39 | ptr: 0,
40 | };
41 |
42 | const buffer = toBuffer('DECODEME');
43 | const reader = new IntBufferReader(buffer, 0, buffer.length);
44 |
45 | while (reader.ptr < reader.buf.length) {
46 | output.buf[output.ptr++] = decodeVLQ(reader);
47 | }
48 |
49 | expect(output.buf).to.deep.equal(new Int32Array([ -1, 2, 1, 7, -1, 2, 6, 2, 0, 0 ]));
50 | expect(output.ptr).to.equal(8);
51 | });
52 |
53 | it('mappings decoder', () => {
54 | // tslint:disable-next-line:max-line-length
55 | const buffer = toBuffer('uLAOA,SAASA,GAAcC,EAAMC,EAAIC,GACjC,OAAUF,GACV,IAAS,SAAT,MAA0B,IAAIG,GAAOF,EAAIC,EAAzC,KACS,cAAT,MAA+B');
56 |
57 | const reader = new IntBufferReader(buffer, 0, buffer.length);
58 |
59 | const decoder = new Decoder();
60 | const mappingsDecoder = new MappingsDecoder(decoder);
61 |
62 | mappingsDecoder.decode(reader);
63 |
64 | expect(decoder.mappings).to.deep.equal([[
65 | { fieldCount: 4, col: 183, src: 0, srcLine: 7, srcCol: 0, name: 0 },
66 | { fieldCount: 5, col: 192, src: 0, srcLine: 7, srcCol: 9, name: 0 },
67 | { fieldCount: 5, col: 195, src: 0, srcLine: 7, srcCol: 23, name: 1 },
68 | { fieldCount: 5, col: 197, src: 0, srcLine: 7, srcCol: 29, name: 2 },
69 | { fieldCount: 5, col: 199, src: 0, srcLine: 7, srcCol: 33, name: 3 },
70 | { fieldCount: 4, col: 202, src: 0, srcLine: 8, srcCol: 0, name: 0 },
71 | { fieldCount: 5, col: 209, src: 0, srcLine: 8, srcCol: 10, name: 1 },
72 | { fieldCount: 4, col: 212, src: 0, srcLine: 9, srcCol: 0, name: 0 },
73 | { fieldCount: 4, col: 216, src: 0, srcLine: 9, srcCol: 9, name: 0 },
74 | { fieldCount: 4, col: 225, src: 0, srcLine: 9, srcCol: 0, name: 0 },
75 | { fieldCount: 4, col: 231, src: 0, srcLine: 9, srcCol: 26, name: 0 },
76 | { fieldCount: 5, col: 235, src: 0, srcLine: 9, srcCol: 30, name: 4 },
77 | { fieldCount: 5, col: 238, src: 0, srcLine: 9, srcCol: 37, name: 2 },
78 | { fieldCount: 5, col: 240, src: 0, srcLine: 9, srcCol: 41, name: 3 },
79 | { fieldCount: 4, col: 242, src: 0, srcLine: 9, srcCol: 0, name: 0 },
80 | { fieldCount: 4, col: 247, src: 0, srcLine: 10, srcCol: 9, name: 0 },
81 | { fieldCount: 4, col: 261, src: 0, srcLine: 10, srcCol: 0, name: 0 },
82 | { fieldCount: 4, col: 267, src: 0, srcLine: 10, srcCol: 31, name: 0 },
83 | ]]);
84 | });
85 |
86 | it('mappings decoder (another)', () => {
87 | // tslint:disable-next-line:max-line-length
88 | const buffer = toBuffer(',YAAY;;AAArB,WAAS,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE;AACjD,QAAI,KAAK,GAAG,CAAC,CAAC;AACd,QAAI,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5B,QAAI,MAAM,EAAE,CAAC,CAAC;;AAEd,WAAO,KAAK,GAAG,GAAG,EAAE;;;AAGlB,OAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAA,GAAI,CAAC,CAAC;;;;AAItB,YAAM,GAAG,KAAK,GAAG,CAAC,GAAI,CAAC,GAAG,CAAC,AAAC,CAAC;;AAE7B,UAAI,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE;AAC1B,aAAK,GAAG,MAAM,GAAG,CAAC,CAAC;OACpB,MAAM;AACL,WAAG,GAAG,MAAM,CAAC;OACd;KACF;;AAED,WAAO,AAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAI,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;GACpD');
89 |
90 | const decoder = new Decoder();
91 | const reader = new IntBufferReader(buffer, 0, buffer.length);
92 |
93 | new MappingsDecoder(decoder).decode(reader);
94 |
95 | const mappings = decoder.mappings;
96 |
97 | expect(mappings.length, 'mappings.length').to.equal(25);
98 | expect(mappings[0].length).to.equal(1);
99 | expect(mappings[0][0], 'YAAY').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 12, src: 0, col: 12, name: 0 });
100 |
101 | expect(mappings[1].length).to.equal(0);
102 | expect(mappings[2].length).to.equal(8);
103 |
104 | expect(mappings[2][0], 'AAArB').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: -9, src: 0, col: 0, name: 0 });
105 | expect(mappings[2][1], 'WAAS').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 0, src: 0, col: 11, name: 0 });
106 | expect(mappings[2][2], 'YAAY').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 12, src: 0, col: 23, name: 0 });
107 | expect(mappings[2][3], 'CAAC').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 13, src: 0, col: 24, name: 0 });
108 | expect(mappings[2][4], 'IAAI').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 17, src: 0, col: 28, name: 0 });
109 | expect(mappings[2][5], 'EAAE').to.deep.equal({ fieldCount: 4, srcLine: 0, srcCol: 19, src: 0, col: 30, name: 0 });
110 | });
111 |
112 | it('encoder', () => {
113 | // (lines + segemnts * 6) = byte_count
114 | const decoded = [[
115 | { fieldCount: 4, col: 183, src: 0, srcLine: 7, srcCol: 0, name: 0 },
116 | { fieldCount: 5, col: 192, src: 0, srcLine: 7, srcCol: 9, name: 0 },
117 | { fieldCount: 5, col: 195, src: 0, srcLine: 7, srcCol: 23, name: 1 },
118 | { fieldCount: 5, col: 197, src: 0, srcLine: 7, srcCol: 29, name: 2 },
119 | { fieldCount: 5, col: 199, src: 0, srcLine: 7, srcCol: 33, name: 3 },
120 | { fieldCount: 4, col: 202, src: 0, srcLine: 8, srcCol: 0, name: 0 },
121 | { fieldCount: 5, col: 209, src: 0, srcLine: 8, srcCol: 10, name: 1 },
122 | { fieldCount: 4, col: 212, src: 0, srcLine: 9, srcCol: 0, name: 0 },
123 | { fieldCount: 4, col: 216, src: 0, srcLine: 9, srcCol: 9, name: 0 },
124 | { fieldCount: 4, col: 225, src: 0, srcLine: 9, srcCol: 0, name: 0 },
125 | { fieldCount: 4, col: 231, src: 0, srcLine: 9, srcCol: 26, name: 0 },
126 | { fieldCount: 5, col: 235, src: 0, srcLine: 9, srcCol: 30, name: 4 },
127 | { fieldCount: 5, col: 238, src: 0, srcLine: 9, srcCol: 37, name: 2 },
128 | { fieldCount: 5, col: 240, src: 0, srcLine: 9, srcCol: 41, name: 3 },
129 | { fieldCount: 4, col: 242, src: 0, srcLine: 9, srcCol: 0, name: 0 },
130 | { fieldCount: 4, col: 247, src: 0, srcLine: 10, srcCol: 9, name: 0 },
131 | { fieldCount: 4, col: 261, src: 0, srcLine: 10, srcCol: 0, name: 0 },
132 | { fieldCount: 4, col: 267, src: 0, srcLine: 10, srcCol: 31, name: 0 },
133 | ]];
134 |
135 | // TODO: pretty sure we can do a Uint8Array here
136 | // let buffer = new Uint32Array(estimatedSize);
137 | const buffer: number[] = [];
138 | const writer = new IntBufferWriter(buffer, 0);
139 | const encoder = new Encoder(writer);
140 | const mappingsEncoder = new MappingsEncoder(encoder);
141 |
142 | mappingsEncoder.encode(decoded);
143 |
144 | expect(buffer.length, 'mapper.encode(decoded)').to.deep.equal(102); // TODO: this number is likely not right...
145 | expect(toString(buffer, 0, buffer.length)).to.deep.equal(
146 | 'uLAOA,SAASA,GAAcC,EAAMC,EAAIC,GACjC,OAAUF,GACV,IAAS,SAAT,MAA0B,IAAIG,GAAOF,EAAIC,EAAzC,KACS,cAAT,MAA+B');
147 | });
148 | });
149 |
--------------------------------------------------------------------------------
/src/utils/read-file.ts:
--------------------------------------------------------------------------------
1 | const fs: FS | undefined = (() => {
2 | if (typeof module === 'object' &&
3 | typeof module.exports === 'object' &&
4 | typeof require === 'function') {
5 | return require('fs');
6 | }
7 | })();
8 |
9 | const readFile: (path: string) => string = fs === undefined ? () => { throw new Error('readFile not supported'); } :
10 | (path) => fs.readFileSync(path, { encoding: 'utf8' });
11 |
12 | interface FS {
13 | readFileSync(path: string, options: { encoding: string }): string;
14 | }
15 |
16 | export default readFile;
17 |
--------------------------------------------------------------------------------
/src/utils/to-buffer.ts:
--------------------------------------------------------------------------------
1 | export default function toBuffer(str: string) {
2 | const buffer = new Uint8Array(str.length);
3 | for (let i = 0; i < buffer.length; i++) {
4 | // this is for base64 so we know these are all < 123
5 | buffer[i] = str.charCodeAt(i) | 0;
6 | }
7 | return buffer;
8 | }
9 |
--------------------------------------------------------------------------------
/src/utils/to-string.ts:
--------------------------------------------------------------------------------
1 | export default function toString(buffer: number[] | Uint8Array, offset: number, len: number) {
2 | let str = '';
3 | for (let i = offset; i < len; i++) {
4 | str += String.fromCharCode(buffer[i]);
5 | }
6 | return str;
7 | }
8 |
--------------------------------------------------------------------------------
/src/vlq.ts:
--------------------------------------------------------------------------------
1 | import { asciiToUint6, uint6ToASCII } from './base64';
2 | import Reader from './reader';
3 | import Writer from './writer';
4 |
5 | // 0 - 63 (6-bit 0 - 111111)
6 | // 32 100000 continuation bit
7 | // 31 011111 mask 5 bits
8 | // 1 is the sign bit
9 | export function encodeVLQ(writer: Writer, v: number) {
10 | let num = v < 0 ? (-v << 1) | 1 : v << 1;
11 | let cont = false;
12 | do {
13 | let digit = num & 31;
14 | num >>= 5;
15 | cont = num > 0;
16 | if (cont) {
17 | digit |= 32;
18 | }
19 | writer.write(uint6ToASCII[digit]);
20 | } while (cont);
21 | }
22 |
23 | export function decodeVLQ(reader: Reader) {
24 | let num = 0;
25 | let shift = 0;
26 | let digit = 0;
27 | let cont = 0;
28 | do {
29 | digit = asciiToUint6[reader.read()];
30 | cont = digit & 32;
31 | digit = digit & 31;
32 | num = num + (digit << shift);
33 | shift += 5;
34 | } while (cont > 0);
35 | return num & 1 ? -(num >> 1) : (num >> 1);
36 | }
37 |
--------------------------------------------------------------------------------
/src/writer.ts:
--------------------------------------------------------------------------------
1 | interface Writer {
2 | length: number;
3 | write(n: number): void;
4 | }
5 |
6 | export default Writer;
7 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "es2015",
4 | "target": "es5",
5 | "sourceMap": true,
6 | "outDir": "lib",
7 | "rootDir": "src",
8 | "declaration": true,
9 | "strict": true
10 | },
11 | "include": [
12 | "src/**/*.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "jsRules": {},
7 | "rules": {
8 | "quotemark": {
9 | "options": "single"
10 | },
11 | "no-console": false,
12 | "no-var-requires": false,
13 | "no-bitwise": false,
14 | "interface-name": false
15 | },
16 | "rulesDirectory": []
17 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/chai@^4.0.4":
6 | version "4.0.4"
7 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.4.tgz#fe86315d9a66827feeb16f73bc954688ec950e18"
8 |
9 | "@types/mocha@^2.2.43":
10 | version "2.2.43"
11 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27"
12 |
13 | "@types/node@^8.0.28":
14 | version "8.0.28"
15 | resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.28.tgz#86206716f8d9251cf41692e384264cbd7058ad60"
16 |
17 | ansi-regex@^2.0.0:
18 | version "2.1.1"
19 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
20 |
21 | ansi-styles@^2.2.1:
22 | version "2.2.1"
23 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
24 |
25 | assertion-error@^1.0.1:
26 | version "1.0.2"
27 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
28 |
29 | babel-code-frame@^6.22.0:
30 | version "6.26.0"
31 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
32 | dependencies:
33 | chalk "^1.1.3"
34 | esutils "^2.0.2"
35 | js-tokens "^3.0.2"
36 |
37 | balanced-match@^1.0.0:
38 | version "1.0.0"
39 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
40 |
41 | brace-expansion@^1.1.7:
42 | version "1.1.8"
43 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
44 | dependencies:
45 | balanced-match "^1.0.0"
46 | concat-map "0.0.1"
47 |
48 | browser-stdout@1.3.0:
49 | version "1.3.0"
50 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
51 |
52 | buffer-crc32@^0.2.5:
53 | version "0.2.13"
54 | resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
55 |
56 | chai@^4.1.2:
57 | version "4.1.2"
58 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c"
59 | dependencies:
60 | assertion-error "^1.0.1"
61 | check-error "^1.0.1"
62 | deep-eql "^3.0.0"
63 | get-func-name "^2.0.0"
64 | pathval "^1.0.0"
65 | type-detect "^4.0.0"
66 |
67 | chalk@^1.1.3:
68 | version "1.1.3"
69 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
70 | dependencies:
71 | ansi-styles "^2.2.1"
72 | escape-string-regexp "^1.0.2"
73 | has-ansi "^2.0.0"
74 | strip-ansi "^3.0.0"
75 | supports-color "^2.0.0"
76 |
77 | check-error@^1.0.1:
78 | version "1.0.2"
79 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
80 |
81 | colors@^1.1.2:
82 | version "1.1.2"
83 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
84 |
85 | commander@2.9.0:
86 | version "2.9.0"
87 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
88 | dependencies:
89 | graceful-readlink ">= 1.0.0"
90 |
91 | commander@^2.9.0:
92 | version "2.11.0"
93 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
94 |
95 | concat-map@0.0.1:
96 | version "0.0.1"
97 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
98 |
99 | concat-stream@^1.5.1:
100 | version "1.6.0"
101 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
102 | dependencies:
103 | inherits "^2.0.3"
104 | readable-stream "^2.2.2"
105 | typedarray "^0.0.6"
106 |
107 | core-util-is@~1.0.0:
108 | version "1.0.2"
109 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
110 |
111 | debug@2.6.8:
112 | version "2.6.8"
113 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
114 | dependencies:
115 | ms "2.0.0"
116 |
117 | deep-eql@^3.0.0:
118 | version "3.0.1"
119 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
120 | dependencies:
121 | type-detect "^4.0.0"
122 |
123 | diff@3.2.0:
124 | version "3.2.0"
125 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
126 |
127 | diff@^3.2.0:
128 | version "3.3.1"
129 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
130 |
131 | es6-promise@^3.1.2:
132 | version "3.3.1"
133 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
134 |
135 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
136 | version "1.0.5"
137 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
138 |
139 | esutils@^2.0.2:
140 | version "2.0.2"
141 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
142 |
143 | fs.realpath@^1.0.0:
144 | version "1.0.0"
145 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
146 |
147 | get-func-name@^2.0.0:
148 | version "2.0.0"
149 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
150 |
151 | glob@7.1.1:
152 | version "7.1.1"
153 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
154 | dependencies:
155 | fs.realpath "^1.0.0"
156 | inflight "^1.0.4"
157 | inherits "2"
158 | minimatch "^3.0.2"
159 | once "^1.3.0"
160 | path-is-absolute "^1.0.0"
161 |
162 | glob@^7.0.5, glob@^7.1.1:
163 | version "7.1.2"
164 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
165 | dependencies:
166 | fs.realpath "^1.0.0"
167 | inflight "^1.0.4"
168 | inherits "2"
169 | minimatch "^3.0.4"
170 | once "^1.3.0"
171 | path-is-absolute "^1.0.0"
172 |
173 | graceful-fs@^4.1.3:
174 | version "4.1.11"
175 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
176 |
177 | "graceful-readlink@>= 1.0.0":
178 | version "1.0.1"
179 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
180 |
181 | growl@1.9.2:
182 | version "1.9.2"
183 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
184 |
185 | has-ansi@^2.0.0:
186 | version "2.0.0"
187 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
188 | dependencies:
189 | ansi-regex "^2.0.0"
190 |
191 | has-flag@^1.0.0:
192 | version "1.0.0"
193 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
194 |
195 | he@1.1.1:
196 | version "1.1.1"
197 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
198 |
199 | inflight@^1.0.4:
200 | version "1.0.6"
201 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
202 | dependencies:
203 | once "^1.3.0"
204 | wrappy "1"
205 |
206 | inherits@2, inherits@^2.0.3, inherits@~2.0.3:
207 | version "2.0.3"
208 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
209 |
210 | isarray@~1.0.0:
211 | version "1.0.0"
212 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
213 |
214 | js-tokens@^3.0.2:
215 | version "3.0.2"
216 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
217 |
218 | json3@3.3.2:
219 | version "3.3.2"
220 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
221 |
222 | lodash._baseassign@^3.0.0:
223 | version "3.2.0"
224 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
225 | dependencies:
226 | lodash._basecopy "^3.0.0"
227 | lodash.keys "^3.0.0"
228 |
229 | lodash._basecopy@^3.0.0:
230 | version "3.0.1"
231 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
232 |
233 | lodash._basecreate@^3.0.0:
234 | version "3.0.3"
235 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
236 |
237 | lodash._getnative@^3.0.0:
238 | version "3.9.1"
239 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
240 |
241 | lodash._isiterateecall@^3.0.0:
242 | version "3.0.9"
243 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
244 |
245 | lodash.create@3.1.1:
246 | version "3.1.1"
247 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
248 | dependencies:
249 | lodash._baseassign "^3.0.0"
250 | lodash._basecreate "^3.0.0"
251 | lodash._isiterateecall "^3.0.0"
252 |
253 | lodash.isarguments@^3.0.0:
254 | version "3.1.0"
255 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
256 |
257 | lodash.isarray@^3.0.0:
258 | version "3.0.4"
259 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
260 |
261 | lodash.keys@^3.0.0:
262 | version "3.1.2"
263 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
264 | dependencies:
265 | lodash._getnative "^3.0.0"
266 | lodash.isarguments "^3.0.0"
267 | lodash.isarray "^3.0.0"
268 |
269 | minimatch@^3.0.2, minimatch@^3.0.4:
270 | version "3.0.4"
271 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
272 | dependencies:
273 | brace-expansion "^1.1.7"
274 |
275 | minimist@0.0.8:
276 | version "0.0.8"
277 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
278 |
279 | minimist@^1.2.0:
280 | version "1.2.0"
281 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
282 |
283 | mkdirp@0.5.1, mkdirp@^0.5.1:
284 | version "0.5.1"
285 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
286 | dependencies:
287 | minimist "0.0.8"
288 |
289 | mocha@^3.5.3:
290 | version "3.5.3"
291 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
292 | dependencies:
293 | browser-stdout "1.3.0"
294 | commander "2.9.0"
295 | debug "2.6.8"
296 | diff "3.2.0"
297 | escape-string-regexp "1.0.5"
298 | glob "7.1.1"
299 | growl "1.9.2"
300 | he "1.1.1"
301 | json3 "3.3.2"
302 | lodash.create "3.1.1"
303 | mkdirp "0.5.1"
304 | supports-color "3.1.2"
305 |
306 | ms@2.0.0:
307 | version "2.0.0"
308 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
309 |
310 | once@^1.3.0:
311 | version "1.4.0"
312 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
313 | dependencies:
314 | wrappy "1"
315 |
316 | path-is-absolute@^1.0.0:
317 | version "1.0.1"
318 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
319 |
320 | path-parse@^1.0.5:
321 | version "1.0.5"
322 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
323 |
324 | pathval@^1.0.0:
325 | version "1.1.0"
326 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
327 |
328 | process-nextick-args@~1.0.6:
329 | version "1.0.7"
330 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
331 |
332 | readable-stream@^2.2.2:
333 | version "2.3.3"
334 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
335 | dependencies:
336 | core-util-is "~1.0.0"
337 | inherits "~2.0.3"
338 | isarray "~1.0.0"
339 | process-nextick-args "~1.0.6"
340 | safe-buffer "~5.1.1"
341 | string_decoder "~1.0.3"
342 | util-deprecate "~1.0.1"
343 |
344 | resolve@^1.3.2:
345 | version "1.4.0"
346 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
347 | dependencies:
348 | path-parse "^1.0.5"
349 |
350 | rimraf@^2.5.2:
351 | version "2.6.2"
352 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
353 | dependencies:
354 | glob "^7.0.5"
355 |
356 | rollup@^0.50.0:
357 | version "0.50.0"
358 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.50.0.tgz#4c158f4e780e6cb33ff0dbfc184a52cc58cd5f3b"
359 |
360 | safe-buffer@~5.1.0, safe-buffer@~5.1.1:
361 | version "5.1.1"
362 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
363 |
364 | sander@^0.5.0:
365 | version "0.5.1"
366 | resolved "https://registry.yarnpkg.com/sander/-/sander-0.5.1.tgz#741e245e231f07cafb6fdf0f133adfa216a502ad"
367 | dependencies:
368 | es6-promise "^3.1.2"
369 | graceful-fs "^4.1.3"
370 | mkdirp "^0.5.1"
371 | rimraf "^2.5.2"
372 |
373 | semver@^5.3.0:
374 | version "5.4.1"
375 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
376 |
377 | sorcery@^0.10.0:
378 | version "0.10.0"
379 | resolved "https://registry.yarnpkg.com/sorcery/-/sorcery-0.10.0.tgz#8ae90ad7d7cb05fc59f1ab0c637845d5c15a52b7"
380 | dependencies:
381 | buffer-crc32 "^0.2.5"
382 | minimist "^1.2.0"
383 | sander "^0.5.0"
384 | sourcemap-codec "^1.3.0"
385 |
386 | source-map@^0.5.6:
387 | version "0.5.7"
388 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
389 |
390 | sourcemap-codec@^1.3.0:
391 | version "1.3.1"
392 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.3.1.tgz#9ad6f9bdbd691931016e30939dbc868673323146"
393 | dependencies:
394 | vlq "^0.2.1"
395 |
396 | string_decoder@~1.0.3:
397 | version "1.0.3"
398 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
399 | dependencies:
400 | safe-buffer "~5.1.0"
401 |
402 | strip-ansi@^3.0.0:
403 | version "3.0.1"
404 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
405 | dependencies:
406 | ansi-regex "^2.0.0"
407 |
408 | supports-color@3.1.2:
409 | version "3.1.2"
410 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
411 | dependencies:
412 | has-flag "^1.0.0"
413 |
414 | supports-color@^2.0.0:
415 | version "2.0.0"
416 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
417 |
418 | tslib@^1.7.1:
419 | version "1.7.1"
420 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec"
421 |
422 | tslint@^5.7.0:
423 | version "5.7.0"
424 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.7.0.tgz#c25e0d0c92fa1201c2bc30e844e08e682b4f3552"
425 | dependencies:
426 | babel-code-frame "^6.22.0"
427 | colors "^1.1.2"
428 | commander "^2.9.0"
429 | diff "^3.2.0"
430 | glob "^7.1.1"
431 | minimatch "^3.0.4"
432 | resolve "^1.3.2"
433 | semver "^5.3.0"
434 | tslib "^1.7.1"
435 | tsutils "^2.8.1"
436 |
437 | tsutils@^2.8.1:
438 | version "2.8.2"
439 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.8.2.tgz#2c1486ba431260845b0ac6f902afd9d708a8ea6a"
440 | dependencies:
441 | tslib "^1.7.1"
442 |
443 | type-detect@^4.0.0:
444 | version "4.0.3"
445 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
446 |
447 | typedarray@^0.0.6:
448 | version "0.0.6"
449 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
450 |
451 | typescript@^2.5.2:
452 | version "2.5.2"
453 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34"
454 |
455 | util-deprecate@~1.0.1:
456 | version "1.0.2"
457 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
458 |
459 | vlq@^0.2.1:
460 | version "0.2.2"
461 | resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1"
462 |
463 | wrappy@1:
464 | version "1.0.2"
465 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
466 |
--------------------------------------------------------------------------------