From e9184b0ea8b2912347a0a11597a545649f96faca Mon Sep 17 00:00:00 2001 From: Ger Hobbelt Date: Tue, 18 Jun 2019 20:05:14 +0200 Subject: [PATCH] make the SourceMap node validation more precise and possibly more performant: check for the okay/good cases before checking the various error situations. Hence the first error check (with its extensive report message) has been moved down. The check has been duplicated for the 'generated' section of the mapping as that's another potential user app programmer error source. The diff is a little large because I turned on `prettier` for all my branches for easier merging/diffing (once one has moved to a `prettier`-formatted codebase). Extracted from SHA-1: 151593b34d72bd106be0e78d8a6edbafaceae489 * stricter validation for source and generated line/column: when they exist, they MUST be numbers. Related to https://github.com/mozilla/source-map/issues/385 (which is not fixed by this, mind you). For this patch I choose to stick with the exception being thrown as that better ensures code/mapping quality AFAIAC. As all error validation checks are now in a single spot and within a single conditional chunk, source-map can choose to resolve by, for example, providing a source-map option which enables/disables these checks. --- lib/source-map-generator.js | 92 ++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/lib/source-map-generator.js b/lib/source-map-generator.js index 8111e061..c756e7f7 100644 --- a/lib/source-map-generator.js +++ b/lib/source-map-generator.js @@ -263,37 +263,73 @@ class SourceMapGenerator { * 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) { + if ( + aGenerated && + typeof aGenerated.line === "number" && + typeof aGenerated.column === "number" && + 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) { + return; + } else if ( + aGenerated && + typeof aGenerated.line === "number" && + typeof aGenerated.column === "number" && + aOriginal && + typeof aOriginal.line === "number" && + typeof aOriginal.column === "number" && + aGenerated.line > 0 && + aGenerated.column >= 0 && + aOriginal.line > 0 && + aOriginal.column >= 0 && + aSource + ) { // Cases 2 and 3. - + return; } else { - throw new Error("Invalid mapping: " + JSON.stringify({ - generated: aGenerated, - source: aSource, - original: aOriginal, - name: aName - })); + let errMsg; + + // 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") + ) { + errMsg = + "original.line and/or 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."; + } + + // When `aGenerated` 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. + else if ( + aGenerated && + (typeof aGenerated.line !== "number" || + typeof aGenerated.column !== "number") + ) { + errMsg = + "generated.line and/or generated.column are not numbers -- you MUST specify " + + "a valid generated position."; + } + + throw new Error( + (errMsg ? errMsg + " " : "") + "Invalid mapping: " + + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + }) + ); } }