-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
inspector: --inspect-brk for ES6 modules #17360
Conversation
Should this be during eval instead of instantiate? |
I did not dig deep, only did manual test. What I saw was that breaking during eval will actually break later then desired - e.g. for this example ( |
Nice to see this. @eugeneo it may be worth trying some alternative wrapper functions as instantiate does sound fairly arbitrary as it does no module execution. Would job.run() at https://github.com/nodejs/node/pull/17360/files#diff-e6f2798544dae1f6ec863621e745489aR141 work perhaps? The other thing that seems non-ideal is having that extra propery from within the ModuleJob class, it would be nice to be able to attach something from outside that way like: initWrapper(moduleJob.run, moduleJob) Let me know if any of these adjustments might work. |
The main problem is that the breakpoint set from the C++ code will be hit when next JS instruction is executed. This means that we need to call this immediately before the user code is invoked. Otherwise breakpoint will be hit in the Node.js JS code and confuse/scare the user :) E.g., replacing From V8 and inspector pov, there is no difference between framework code (e.j. ModuleJob#run) and user code. But DevTools really want to break in the user code. |
@eugeneo Is there a way to blackbox the inspector scripts by default? |
Chrome does not use blackboxing in scenarios like this so it had been designed to be controlled by the front-end. Currently blackboxing is per-session and is only available through the inspector protocol. E.g. Node would have to intercept |
@eugeneo thanks for the clarification, I guess I'm just completely not understanding how |
One of the tests I did was this script:
Breaking on initialization correctly steps over initialization of the |
@eugeneo I think that might be because you were breaking on the top level instead of the deepest leaf. Since ESM evaluates in post order traversal, the deepest leaf evaluates first. |
This break is supposed to break once before any code was executed. There should be no modules loaded but the main one. |
@eugeneo compiled locally and played around, I think this timing is the most consistent to how CJS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with some test nits.
const { NodeInstance } = require('../common/inspector-helper.js'); | ||
|
||
function checkListResponse(response) { | ||
assert.strictEqual(1, response.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nit: reverse the argument order here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, here and below.
'Browser': `node.js/${process.version}`, | ||
'Protocol-Version': '1.1', | ||
}; | ||
assert.strictEqual(JSON.stringify(response), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert.deepStrictEqual()
without the JSON.stringify()
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
function checkBadPath(err) { | ||
assert(err instanceof SyntaxError); | ||
assert(/Unexpected token/.test(err.message), err.message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error comes from the engine, not Node, right? If so, we shouldn't validate the message
, as it could be different from V8 to Chakra.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a hardcoded string - but there's no reason to test this here, it is covered by the main inspector test. I removed it.
} | ||
|
||
function assertNoUrlsWhileConnected(response) { | ||
assert.strictEqual(1, response.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverse the argument order here please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
unmatched.delete(actual['name']); | ||
} | ||
} | ||
if (unmatched.size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you write this as assert.strictEqual(unmatched.size, 0)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to comparison to an empty array.
const unmatched = new Set(Object.keys(expected)); | ||
for (const actual of result) { | ||
const value = expected[actual['name']]; | ||
if (value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this if
necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Removed.
} | ||
}); | ||
|
||
assert.strictEqual(1002, result['value']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll stop mentioning it, but could you switch the order of the arguments here and in other places so that it is actual
then expected
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, and works perfectly!
It does worry me that instantiate
ends up being the break point over module.execute
though, that seems a v8 bug to me.
CI seems to be unhappy. See https://ci.nodejs.org/job/node-test-binary-windows/13247/COMPILED_BY=vs2017,RUNNER=win2016,RUN_SUBSET=0/console. |
Script URL format is different on different configurations. I will make the test more resilient, but it looks like there's an issue in the Node core. |
@eugeneo this looks good, thanks for digging into this. I'm about to check out this branch and test whether the inspector stops in time for detailed coverage to be enabled in the inspector. |
test/common/inspector-helper.js
Outdated
|
||
const _MAINSCRIPT = fixtures.path('loop.js'); | ||
const DEBUG = false; | ||
const TIMEOUT = common.platformTimeout(15 * 1000); | ||
|
||
function filePathToUrl(path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use require('internal/url').getURLFromFilePath
instead.
} | ||
|
||
scriptURL() { | ||
return new URL(this.scriptPath(), 'file:').toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
Windows CI is still unhappy. https://ci.nodejs.org/job/node-test-binary-windows/13277/ |
Just wondering what stalled here? Would be great to see this moving. Btw @chrisdickinson has an interesting variation on this approach which may be a little bit more sensible, see 1d771f5#diff-46b46cfa0c77bff7ab6ed3fcb584e728R102. |
It's probably worth someone closing related issues, it's not easy to navigate through the dupes of this one |
@guybedford, @chrisdickinson's changes look good to me if you can file a separate PR, with the caveat that |
@TimothyGu I tested out the approach and it seems to have the same problem as mentioned before of not exactly getting exactly the first line but instead getting loader internals. So this still remains the best approach it seems. |
Reworked rebase of PR nodejs#17360 with feedback
Landed through reworked PR in e7ff00d. |
Awesome. Does anyone know when the next release will occur? I'm drooling over this one |
Reworked rebase of PR nodejs#17360 with feedback PR-URL: nodejs#18194 Fixes: nodejs#17340 Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Fixes: #17340
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
ES6 module loader, test: added a hook to break on module init and a test