From ef6e4c95c2f7264d1bcd6abfb8365d0550b5b917 Mon Sep 17 00:00:00 2001 From: milahu Date: Mon, 24 Aug 2020 13:59:26 +0200 Subject: [PATCH 1/4] support arbitrary keys now users must append `jsonMap.leaf_node` to their `keyList` like ```js const jsonMap = require('json-source-map'); const result = jsonMap.parse('{"z":1,"a":{"z":1,"a":1}}'); let pointer = result.pointers; for (let key of keyList.concat([jsonMap.leaf_key])) { pointer = pointer[key]; } const [a, b] = [pointer.value.pos, pointer.valueEnd.pos]; ``` --- index.js | 92 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/index.js b/index.js index dbf5860..b72725e 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,8 @@ var escapedChars = { var A_CODE = 'a'.charCodeAt(); +const leaf_key = '____jsonSourceMapLeafNode'; +exports.leaf_key = leaf_key; exports.parse = function (source, _, options) { var pointers = {}; @@ -21,22 +23,22 @@ exports.parse = function (source, _, options) { var pos = 0; var bigint = options && options.bigint && typeof BigInt != 'undefined'; return { - data: _parse('', true), + data: _parse([], true), pointers: pointers }; - function _parse(ptr, topLevel) { + function _parse(keyList, topLevel) { whitespace(); var data; - map(ptr, 'value'); + map(keyList, 'value'); var char = getChar(); switch (char) { case 't': read('rue'); data = true; break; case 'f': read('alse'); data = false; break; case 'n': read('ull'); data = null; break; case '"': data = parseString(); break; - case '[': data = parseArray(ptr); break; - case '{': data = parseObject(ptr); break; + case '[': data = parseArray(keyList); break; + case '{': data = parseObject(keyList); break; default: backChar(); if ('-0123456789'.indexOf(char) >= 0) @@ -44,7 +46,7 @@ exports.parse = function (source, _, options) { else unexpectedToken(); } - map(ptr, 'valueEnd'); + map(keyList, 'valueEnd'); whitespace(); if (topLevel && pos < source.length) unexpectedToken(); return data; @@ -113,7 +115,7 @@ exports.parse = function (source, _, options) { : result; } - function parseArray(ptr) { + function parseArray(keyList) { whitespace(); var arr = []; var i = 0; @@ -121,8 +123,8 @@ exports.parse = function (source, _, options) { backChar(); while (true) { - var itemPtr = ptr + '/' + i; - arr.push(_parse(itemPtr)); + var itemKeyList = keyList.concat([i]); + arr.push(_parse(itemKeyList)); whitespace(); var char = getChar(); if (char == ']') break; @@ -133,7 +135,7 @@ exports.parse = function (source, _, options) { return arr; } - function parseObject(ptr) { + function parseObject(keyList) { whitespace(); var obj = {}; if (getChar() == '}') return obj; @@ -143,13 +145,13 @@ exports.parse = function (source, _, options) { var loc = getLoc(); if (getChar() != '"') wasUnexpectedToken(); var key = parseString(); - var propPtr = ptr + '/' + escapeJsonPointer(key); - mapLoc(propPtr, 'key', loc); - map(propPtr, 'keyEnd'); + var propKeyList = keyList.concat([key]); + mapLoc(propKeyList, 'key', loc); + map(propKeyList, 'keyEnd'); whitespace(); if (getChar() != ':') wasUnexpectedToken(); whitespace(); - obj[key] = _parse(propPtr); + obj[key] = _parse(propKeyList); whitespace(); var char = getChar(); if (char == '}') break; @@ -203,13 +205,19 @@ exports.parse = function (source, _, options) { unexpectedToken(); } - function map(ptr, prop) { - mapLoc(ptr, prop, getLoc()); + function map(keyList, prop) { + mapLoc(keyList, prop, getLoc()); } - function mapLoc(ptr, prop, loc) { - pointers[ptr] = pointers[ptr] || {}; - pointers[ptr][prop] = loc; + function mapLoc(keyList, prop, loc) { + let item = pointers; + for (let k of keyList.concat([leaf_key])) { + if (item[k] === undefined) { + item[k] = {}; + } + item = item[k]; + } + item[prop] = loc; } function getLoc() { @@ -286,8 +294,8 @@ exports.stringify = function (data, _, options) { pointers: pointers }; - function _stringify(_data, lvl, ptr) { - map(ptr, 'value'); + function _stringify(_data, lvl, keyList) { + map(keyList, 'value'); switch (typeof _data) { case 'number': case 'bigint': @@ -315,7 +323,7 @@ exports.stringify = function (data, _, options) { stringifyObject(); } } - map(ptr, 'valueEnd'); + map(keyList, 'valueEnd'); function stringifyArray() { if (_data.length) { @@ -325,8 +333,8 @@ exports.stringify = function (data, _, options) { if (i) out(','); indent(itemLvl); var item = validType(_data[i]) ? _data[i] : null; - var itemPtr = ptr + '/' + i; - _stringify(item, itemLvl, itemPtr); + var itemKeyList = keyList.concat([i]); + _stringify(item, itemLvl, itemKeyList); } indent(lvl); out(']'); @@ -345,14 +353,14 @@ exports.stringify = function (data, _, options) { var value = _data[key]; if (validType(value)) { if (i) out(','); - var propPtr = ptr + '/' + escapeJsonPointer(key); + var propKeyList = keyList.concat([key]); indent(propLvl); - map(propPtr, 'key'); + map(propKeyList, 'key'); out(quoted(key)); - map(propPtr, 'keyEnd'); + map(propKeyList, 'keyEnd'); out(':'); if (whitespace) out(' '); - _stringify(value, propLvl, propPtr); + _stringify(value, propLvl, propKeyList); } } indent(lvl); @@ -376,14 +384,14 @@ exports.stringify = function (data, _, options) { if (validType(value)) { if (!first) out(','); first = false; - var propPtr = ptr + '/' + escapeJsonPointer(key); + var propKeyList = keyList.concat([key]); indent(propLvl); - map(propPtr, 'key'); + map(propKeyList, 'key'); out(quoted(key)); - map(propPtr, 'keyEnd'); + map(propKeyList, 'keyEnd'); out(':'); if (whitespace) out(' '); - _stringify(value, propLvl, propPtr); + _stringify(value, propLvl, propKeyList); } entry = entries.next(); } @@ -419,9 +427,15 @@ exports.stringify = function (data, _, options) { } } - function map(ptr, prop) { - pointers[ptr] = pointers[ptr] || {}; - pointers[ptr][prop] = { + function map(keyList, prop) { + let item = pointers; + for (let k of keyList.concat([leaf_key])) { + if (item[k] === undefined) { + item[k] = {}; + } + item = item[k]; + } + item[prop] = { line: line, column: column, pos: pos @@ -455,11 +469,3 @@ function quoted(str) { .replace(ESC_T, '\\t'); return '"' + str + '"'; } - - -var ESC_0 = /~/g; -var ESC_1 = /\//g; -function escapeJsonPointer(str) { - return str.replace(ESC_0, '~0') - .replace(ESC_1, '~1'); -} From 18776e63a28eb92a3d5333291a2b2fe1c530cd70 Mon Sep 17 00:00:00 2001 From: milahu Date: Mon, 24 Aug 2020 14:08:15 +0200 Subject: [PATCH 2/4] rm const --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index b72725e..12196fa 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,7 @@ var escapedChars = { var A_CODE = 'a'.charCodeAt(); -const leaf_key = '____jsonSourceMapLeafNode'; +var leaf_key = '____jsonSourceMapLeafNode'; exports.leaf_key = leaf_key; exports.parse = function (source, _, options) { From 14f5af6af727d3deb388c4dafe4d19d710843461 Mon Sep 17 00:00:00 2001 From: milahu Date: Mon, 24 Aug 2020 14:26:42 +0200 Subject: [PATCH 3/4] lint --- index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 12196fa..151c6bd 100644 --- a/index.js +++ b/index.js @@ -212,9 +212,8 @@ exports.parse = function (source, _, options) { function mapLoc(keyList, prop, loc) { let item = pointers; for (let k of keyList.concat([leaf_key])) { - if (item[k] === undefined) { + if (item[k] === undefined) item[k] = {}; - } item = item[k]; } item[prop] = loc; @@ -430,9 +429,8 @@ exports.stringify = function (data, _, options) { function map(keyList, prop) { let item = pointers; for (let k of keyList.concat([leaf_key])) { - if (item[k] === undefined) { + if (item[k] === undefined) item[k] = {}; - } item = item[k]; } item[prop] = { From 37dd775462a34046a9f3437665973b96f5b48c6c Mon Sep 17 00:00:00 2001 From: milahu Date: Mon, 24 Aug 2020 14:28:27 +0200 Subject: [PATCH 4/4] ecma 11 --- .eslintrc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index 9c70e88..6f61a79 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,4 +1,6 @@ extends: eslint:recommended +parserOptions: + ecmaVersion: 11 env: node: true browser: true