Skip to content
This repository was archived by the owner on Apr 3, 2024. It is now read-only.

Add improved support for transpiled code#159

Merged
DominicKramer merged 38 commits intogoogleapis:masterfrom
DominicKramer:master
Oct 28, 2016
Merged

Add improved support for transpiled code#159
DominicKramer merged 38 commits intogoogleapis:masterfrom
DominicKramer:master

Conversation

@DominicKramer
Copy link
Copy Markdown
Contributor

A Sourcemapper class was introduced that provides improved support for transpiled code and has been tested with Babel, Coffeescript, and Typescript.

In particular, v8debugapi.js uses 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".

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.
@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Oct 14, 2016
@DominicKramer
Copy link
Copy Markdown
Contributor Author

@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.

@Splaktar Splaktar mentioned this pull request Oct 14, 2016
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.
assert.strictEqual(polyfill.endsWith('some text', 'TEXT'), false);
done();
});
}); No newline at end of file

This comment was marked as spam.


// ---------------------- supplemental information ------------------------

/*

This comment was marked as spam.

This comment was marked as spam.

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.

* @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.

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.
@DominicKramer
Copy link
Copy Markdown
Contributor Author

@GoogleCloudPlatform/node-team PTAL

This follows the naming convention of private members used in
the other files in the project.
@@ -0,0 +1,173 @@
/**
* Copyright 2015 Google Inc. All Rights Reserved.

This comment was marked as spam.

lib/polyfill.js Outdated
@@ -0,0 +1,26 @@
/**
* Copyright 2015 Google Inc. All Rights Reserved.

This comment was marked as spam.

* @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.

return;
}

try {

This comment was marked as spam.

*/
var outputBase = consumer.file ? consumer.file
: path.basename(mapPath, '.map'),
parentDir = path.dirname(mapPath),

This comment was marked as spam.

else {
var line = breakpoint.location.line,
column = 0,
mapInfo = sourceMapper.mappingInfo(baseScriptPath, line, column);

This comment was marked as spam.

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.
@DominicKramer
Copy link
Copy Markdown
Contributor Author

@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.

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.

* processing the given sourcemap files
* @constructor
*/
function Sourcemapper(sourcemapPaths, logger) {

This comment was marked as spam.

This comment was marked as spam.

* processing the given sourcemap files
* @constructor
*/
function Sourcemapper(sourcemapPaths, logger) {

This comment was marked as spam.

that.api_ = new SourcemapperApi(that.infoMap_);

_.forEach(that.waitingCallQueue_, function(callback){
process.nextTick(function() {

This comment was marked as spam.

* 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()`.
@DominicKramer
Copy link
Copy Markdown
Contributor Author

DominicKramer commented Oct 25, 2016

@GoogleCloudPlatform/node-team PTAL

I've updated the code to only use callbacks. In particular, debuglet.js now uses SourceMapper.create() to create a SourceMapper that is provided through a callback. That SourceMapper is then supplied to v8debugapi.create().

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.
};
});

async.parallel(callList, function(err) {

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

// 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.

In particular, the use of `async.parallel()` was replaced with
`async.parallelLimit()` to prevent too many parallel I/O
operations from occurring in parallel.
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.

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.

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.

});

callback(null);
setImmediate(function() {

This comment was marked as spam.

This comment was marked as spam.

Copy link
Copy Markdown
Contributor

@ofrobots ofrobots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Please squash before landing.

@DominicKramer DominicKramer merged commit f8bb4dc into googleapis:master Oct 28, 2016
This was referenced Nov 9, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants