Add improved support for transpiled code#159
Add improved support for transpiled code#159DominicKramer merged 38 commits intogoogleapis:masterfrom
Conversation
If an error occurs when re-registering a debuggee, the name of the debuggee is reported in the error message to aid in debugging why the re-registration failed. fixes googleapis#128
The debugletapi#init() method was updated to accept a callback of the form 'callback(err, project)' instead of 'callback(err)'. The test code for the class was updated so that callbacks now include the 'project' parameter.
When the debugletapi.init() method calls its callback, the project ID reported in the callback should match the project ID stored in the debugletapi object.
The testing of the debugletapi#init() method was updated so that the project name given through the callback was the project name expected.
Now the test for the debugletapi#init() method doesn't stub out the utils.getProjectNumber method because it is already being stubbed out earlier in the code.
The tests in teh test-debugletapi.js file assumed the GCLOUD_PROJECT environment variable was not set, and would fail if this assumption wasn't valid. Now the GCLOUD_PROJECT environment variable is unset when running this file.
Two resolve a line in an input file to a line in a transpiled output file, two things needed to be fixed: 1. The line number given to a SourceMapConsumer needs to be one-based. 2. The path given to a SourceMapConsumer needs to be relative to the path of the sourcemap used to build the consumer.
The SourceMapConsumer#generatedPositionFor() seems to return an incorrect line number. sourcemapper.js has been updated to use the SourceMapConsumer#allGeneratedPositionsFor() method that seems to return the correct line number. This has been confirmed using the newly added unit tests that verifies line mappings that were confirmed manually.
The fix consisted of: 1. using the path.resolve() method to resolve a realtive path to its absolute path 2. moving test-sourcemapper.js to the 'test/standalone' directory
The unit test in question is now no longer needed based on the introduction of sourcemapper.js.
|
@GoogleCloudPlatform/node-team PTAL |
The unit test in question tested that an error was thrown if the `endsWith` function was supplied `null` or `undefined`. However, this behavior is different on Node v0.12 compared to Node 4, 5, and 6. The unit test to address these differences will be added at a later time.
lib/polyfill.js
Outdated
| @@ -0,0 +1,26 @@ | |||
| /** | |||
| * Copyright 2015 Google Inc. All Rights Reserved. | |||
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This commit fixes a bug where after a breakpoint was hit in a source file that was the input to a transpilation process, the breakpoint would be correctly hit, but the breakpoint's line number would incorrectly get changed.
test/test-polyfill.js
Outdated
| assert.strictEqual(polyfill.endsWith('some text', 'TEXT'), false); | ||
| done(); | ||
| }); | ||
| }); No newline at end of file |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/standalone/test-sourcemapper.js
Outdated
|
|
||
| // ---------------------- supplemental information ------------------------ | ||
|
|
||
| /* |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/polyfill.js
Outdated
| if (typeof String.prototype.endsWith === 'function') { | ||
| return str.endsWith(suffix); | ||
| } else { | ||
| return str.indexOf(suffix, str.length - suffix.length) !== -1; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| * @param {string} inputPath The absolute path to an input file that could | ||
| * possibly be the input to a transpilation process | ||
| */ | ||
| Sourcemapper.prototype.hasMappingInfo = function(inputPath) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
In particular, the lodash#endsWith method will now be used so that polyfill.js is not needed.
A new `test/fixtures/sourcemapper` directory was made to hold the input, output, sourcemap, and build files for the data used in the updated `test-sourcemapper.js` file.
|
@GoogleCloudPlatform/node-team PTAL |
This follows the naming convention of private members used in the other files in the project.
lib/sourcemapper.js
Outdated
| @@ -0,0 +1,173 @@ | |||
| /** | |||
| * Copyright 2015 Google Inc. All Rights Reserved. | |||
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/polyfill.js
Outdated
| @@ -0,0 +1,26 @@ | |||
| /** | |||
| * Copyright 2015 Google Inc. All Rights Reserved. | |||
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| * @param {!function(?Error, Array<string>)} callback error-back callback | ||
| */ | ||
| function findJSFiles(baseDir, callback) { | ||
| function findFiles(baseDir, regex, callback) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| return; | ||
| } | ||
|
|
||
| try { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| */ | ||
| var outputBase = consumer.file ? consumer.file | ||
| : path.basename(mapPath, '.map'), | ||
| parentDir = path.dirname(mapPath), |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/v8debugapi.js
Outdated
| else { | ||
| var line = breakpoint.location.line, | ||
| column = 0, | ||
| mapInfo = sourceMapper.mappingInfo(baseScriptPath, line, column); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
In particular, the new Sourcemapper#do() function is the main access point for the Sourcemapper that allows Sourcemapper methods to be safely used even though the Sourcemapper's constructor is asynchronous.
The SourcemapperApi class encapsulates the Sourcemapper's public API and is only exposed through the Sourcemapper#do function. This ensures a Sourcemapper's methods are only used through a Sourcemapper#do method and not directly.
|
@GoogleCloudPlatform/node-team PTAL. There is a stacktrace printed out when the unit tests are run, but the tests still pass. I will look into this, but I wanted to get feedback on the current code. |
| * In particular, the generatedPositionFor() alone doesn't appear to | ||
| * give the correct mapping information. | ||
| */ | ||
| var mappedPos = allPos && allPos.length > 0 ? |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
| Array.prototype.reduce.call(allPos, | ||
| function(accumulator, value, index, arr) { | ||
| return value.line < accumulator.line ? value : accumulator; | ||
| }) : consumer.generatedPositionFor(sourcePos); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| * processing the given sourcemap files | ||
| * @constructor | ||
| */ | ||
| function Sourcemapper(sourcemapPaths, logger) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| * processing the given sourcemap files | ||
| * @constructor | ||
| */ | ||
| function Sourcemapper(sourcemapPaths, logger) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| that.api_ = new SourcemapperApi(that.infoMap_); | ||
|
|
||
| _.forEach(that.waitingCallQueue_, function(callback){ | ||
| process.nextTick(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
* Renamed `Sourcemapper` to `SourceMapper` * Now the `SourceMapper.create()` method is used to create a `SourceMapper` and the constructed `SourceMapper` is passed to the callback supplied to the `create()` method. * Updated `v8debugapi.create()` to accept a `SourceMapper` * Updated `debuglet.js` to create a SourceMapper
The `scanner.scan()` method now provides a `ScanResults` object to its callback. This new class provides the `selectStats()`, `selectFiles()`, and `all()` methods to eliminate duplication of code that was filtering results obtained from `scanner.scan()`.
|
@GoogleCloudPlatform/node-team PTAL I've updated the code to only use callbacks. In particular, I've also made changes that should address all of the comments made so far. |
In particular, the filesystem on my local machine is not case sensitive in this respect and so locally unit tests were passing but they were failing in CI.
lib/sourcemapper.js
Outdated
| }; | ||
| }); | ||
|
|
||
| async.parallel(callList, function(err) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| // this handles the case when the path is undefined, null, or | ||
| // the empty string | ||
| if (!mapPath || !_.endsWith(mapPath, MAP_EXT)){ | ||
| return callback(new Error('The path ' + mapPath + |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
In particular, the use of `async.parallel()` was replaced with `async.parallelLimit()` to prevent too many parallel I/O operations from occurring in parallel.
lib/sourcemapper.js
Outdated
| if (err){ | ||
| return callback(new Error('Could not read sourcemap file ' + mapPath + | ||
| ': ' + err)); | ||
| return setImmediate(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| catch(e) { | ||
| return callback(new Error('An error occurred while reading the '+ | ||
| 'sourcemap file ' + mapPath + ': ' + e)); | ||
| return setImmediate(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| if (sources.length === 0) { | ||
| return callback(new Error('No sources listed in the sourcemap file ' + | ||
| mapPath)); | ||
| return setImmediate(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
lib/sourcemapper.js
Outdated
| }); | ||
|
|
||
| callback(null); | ||
| setImmediate(function() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
ofrobots
left a comment
There was a problem hiding this comment.
LGTM. Please squash before landing.
A Sourcemapper class was introduced that provides improved support for transpiled code and has been tested with Babel, Coffeescript, and Typescript.
In particular,
v8debugapi.jsuses a Sourcemapper to understand the connections between a source file and the transpiled code associated with that source file (if that source file has transpiled code associated with it). For this to work, the transpilation process used to generate the transpiled code needs to also generate sourcemap files.This pull request also fixes bug #153 "Off-by-one-line error in transpiled breakpoint".