-
Notifications
You must be signed in to change notification settings - Fork 341
deps: chakrashim enable JavaScript debugging #126
deps: chakrashim enable JavaScript debugging #126
Conversation
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.
Did a cosmetic review since I'm assuming this was reviewed when the changes where made in the debugging branch- overall, LGTM
if (!('text' in obj)) { | ||
obj['text'] = obj['display']; | ||
} | ||
if (!('className' in obj)) { |
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.
Curious- why is this within the 'display' in obj case? Should this be in 'type' in obj? Also, curious, do you need to use in here or would hasOwnProperty suffice? #Resolved
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.
If you look at JsrtDebugUtils::AddPropertyType, we always add "type" but className in only for few cases. This adding of className as type is to satisfy VSCode.
hasOwnProperty will do but it seems most of the place we use in to check for property.
In reply to: 81491092 [](ancestors = 81491092)
} | ||
|
||
var PROPERTY_ATTRIBUTE_HAVE_CHILDRENS = 0x1; | ||
//var PROPERTY_ATTRIBUTE_READ_ONLY_VALUE = 0x2; |
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.
Nit: remove commented code? #WontFix
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.
Currently we don't use the read only attribute, but I will keep it here for clarity.
In reply to: 81491126 [](ancestors = 81491126)
|
||
ChakraDebugEventProcessor.prototype[ChakraDebugEvent.SourceCompile] = | ||
function() { | ||
// {"fileName":"d:\\test.js","lineCount":4,"sourceLength":113,"scriptId":2} |
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.
remove commented out line? #Resolved
} | ||
|
||
Debug::messageQueue.debugEventProcessCount++; |
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 always called on the same thread? If not, should this be interlocked? #ByDesign
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.
JsDiagDebugEventHandler is supposed to be per runtime, so it is only called from one runtime at a time. No need for interlock.
In reply to: 81492243 [](ancestors = 81492243)
} | ||
|
||
void MessageQueue::SaveMessage(const uint16_t* command, int length) { | ||
uint16_t* msg = new uint16_t[length + 1]; |
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.
Where is this msg deleted? Might be good to add a comment here on the lifetime semantics of this allocation. #Resolved
@digitalinfinity This changes were not reviewed previously |
function Response(request) { | ||
this.seq = _nextResponseSeq++; | ||
this.type = 'response'; | ||
this.request_seq = request.seq; |
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.request_seq
unused property ? #ByDesign
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 is part of debugging protocol https://github.com/v8/v8/wiki/Debugging-Protocol
In reply to: 81944574 [](ancestors = 81944574)
if (filter == element.GetFileName()) { | ||
found = true; | ||
} | ||
} |
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.
from 652
to 655
can be simplified into one line
found = filter == element.GetFileName(); #Resolved
buffer[_countof(chakra_debug_native)] = L'\0'; | ||
|
||
JsValueRef getInitFunction; | ||
if (JsParseScriptWithAttributes(buffer, |
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'm not sure if this works on xplat. Reminder: [unix wchar_t 4 bytes] #Resolved
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.
Debugging support is not xplat ready yet, once we have xplat string APIs we need to use that and make some changes. Take a look at https://github.com/agarwal-sandeep/node-chakracore/blob/debugging-vscode-xplat-jc/deps/chakrashim/src/v8debug.cc which uses the prototype xplat string APIs. #Resolved
this->msgQueue = nullptr; | ||
} | ||
|
||
void MessageQueue::SaveMessage(const uint16_t* command, int 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.
uint16_t
and wchar_t
? (2 bytes / 4 bytes) #Resolved
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.
On windows uint16_t and wchar_t are both 2 bytes and debugging support is currently only for windows. I have a static_assert to make sure we fix this for xplat #Resolved
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 there reason to use 2 different types? (Why not avoid wchar_t and only use uint16_t and use v8::String where string is needed.)
In reply to: 82074191 [](ancestors = 82074191)
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.
Thanks! removed wchar_t usage and instead used v8::String::NewFromTwoByte
In reply to: 82251507 [](ancestors = 82251507,82074191)
JsValueRef args[] = { jsrt::GetUndefined(), debugEventRef }; | ||
JsValueRef result; | ||
errorCode = JsCallFunction( | ||
this->processShouldContinueFn, args, _countof(args), &result); |
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.
Do we have a definition for _countof
non-pal ? #Resolved
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.
@@ -4250,6 +4245,13 @@ void Init(int* argc, | |||
exit(9); | |||
} | |||
|
|||
// CHAKRA-TODO : fix this to not do it 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.
HAKRA-TODO : fix this to not do it here [](start = 6, length = 39)
What is the problem here? #ByDesign
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 problem, but I would like to find a way to not make any NODE_ENGINE_CHAKRACORE specific change to node.cc and somehow determine this in shim itself #ByDesign
@@ -59,12 +63,6 @@ IsolateShim::~IsolateShim() { | |||
} | |||
|
|||
/* static */ v8::Isolate * IsolateShim::New() { | |||
// CHAKRA-TODO: Disable multiple isolate for now until it is fully implemented |
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.
CHAKRA-TODO: Disable multiple isolate for now until it is fully implemented [](start = 5, length = 75)
Has this changed now? Why is this removed? #ByDesign
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.
Because now we need atleast 2 isolate (one main isolate and another for debugger agent). #Resolved
|
||
CHAKRA_VERIFY_NOERROR(errorCode); | ||
|
||
return errorCode == JsNoError; |
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.
rrorCode == JsNoError; [](start = 10, length = 22)
nit: won't this always be true given that you have CHAKRA_VERIFY_NOERROR(errorCode); above? #Resolved
@@ -447,6 +451,46 @@ bool ContextShim::ExecuteChakraShimJS() { | |||
&result) == JsNoError; | |||
} | |||
|
|||
bool ContextShim::ExecuteChakraDebugShimJS(JsValueRef * chakraDebugObject) { |
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.
ExecuteChakraDebugShimJS [](start = 18, length = 24)
suggestion : can we extract out common code of ExecuteChakraDebugShimJS and ExecuteChakraShimJS because in future we might have additional shim.js files that we will execute? #WontFix
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 though of that but that will make things a bit complicated as we need to allocate buffer using new and then in all failure cases make sure it is deleted, Also there not not much command code. We call different APIs in both functions. For now I think we used keep it as it is and if we add more shim then we should definitely refactor this.
In reply to: 82066039 [](ancestors = 82066039)
|
||
if (v8::Debug::IsDebugEnabled() && isoShim->debugContext == nullptr) { | ||
// If JavaScript debugging APIs need to be exposed then make sure | ||
// debugContext is avaliable and chakra_debug.js is compiled. Inject |
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.
avaliable [](start = 23, length = 9)
nit: spelling #Resolved
error: | ||
#else | ||
hr = E_FAIL; // ChakraCore does not support JsStartDebugging | ||
static JsValueRef CALLBACK Log( |
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.
Log [](start = 29, length = 3)
If i understand correctly is this for debugging the debugger code and will never called from user scenario? #ByDesign
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.
Yes #Resolved
return returnRef; | ||
} | ||
|
||
static JsValueRef CALLBACK JsSetBreakpoint( |
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.
JsSetBreakpoint [](start = 29, length = 15)
Can you different nomenclature for these methods? Usually Js*() methods are Jsrt APIs. Would be good to reflect that these are shim methods. #WontFix
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.
all jsrt debugging APIs are named JsDiag* so I choose this name, would keep it this way. #Closed
} | ||
}; | ||
var properties = []; | ||
for (var propsLen = 0; propsLen < propertiesArray.length; ++propsLen) { |
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.
for (va [](start = 8, length = 7)
suggestion : some of the for-loops and foreach can be converted to .map() #Resolved
ExecutionState.prototype.GetObjectEvalHandle = function() { | ||
if (!this.objectEval) { | ||
var objEval = CallHostFunction(chakraDebug.JsDiagEvaluate, 'Object', 0); | ||
this.objectEval = objEval[1]; |
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.
bjEval[1] [](start = 25, length = 9)
If i understand correctly, objEval[0] holds if call succeed or not. You never check that? #Resolved
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.
Should never fail as we are trying to get the global 'Object' #Resolved
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.
Ok. Can we have some an if-check saying if it fails then something bad is going on? #Resolved
success = true; | ||
DebugManager.BreakpointManager.AddBreakpoint(v8Breakpoint); | ||
} | ||
// ToDo: Add to list |
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.
/ ToDo: Add to list [](start = 7, length = 19)
Is this still a TODO? #Resolved
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.
} else if (remove_flags && | ||
(startsWith( | ||
arg, "--debug") // Ignore some flags to reduce unit test noise | ||
|| startsWith(arg, "--harmony") | ||
|| startsWith(arg, "--stack-size="))) { | ||
|| startsWith(arg, "--stack-size=") | ||
|| startsWith(arg, "--nolazy"))) { |
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.
"--nolazy") [](start = 35, length = 11)
why this change? #ByDesign
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.
Its like disabling deferred parsing in V8, VSCode by defaults add this flag so we need to ignore it. #ByDesign
#include <v8.h> | ||
#include "uv.h" | ||
#include <queue> |
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.
nit: cpplint demands <...> before "..." includes. #Resolved
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.
strange I ran cpplint and didn't see any warning/error. I will run again. #Resolved
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.
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.
Made the change but cpplint.py is not showing at as a error/warning
In reply to: 82240850 [](ancestors = 82240850,82239941)
|
||
namespace v8 { | ||
class V8_EXPORT MessageQueue { | ||
public: | ||
MessageQueue(); |
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.
nit: cpplint / consistency prefers these to be 2-space indented. #Pending
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.
Strange, cpplint doesn't show any error/warning with current spacing but if I make it 2 space cpplint is giving error.
In reply to: 82239807 [](ancestors = 82239807)
static MaybeLocal<Value> GetMirror(Local<Context> context, | ||
Handle<Value> obj) { | ||
return MaybeLocal<Value>(); | ||
} | ||
static void StartDebugging(JsRuntimeHandle runtime); |
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 recall v8::Debug is a public class in v8 headers. These look like deviate from v8 signature. Do we need to put them here, or can we move them to private headers?
Same question to other new classes in this file. #Resolved
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.
enabledLogType[logTypes.API] = false; // For development purpose | ||
enabledLogType[logTypes.Output] = traceDebugJson === true; | ||
enabledLogType[logTypes.Input] = traceDebugJson === true; | ||
enabledLogType[logTypes.Error] = false; // For development purpose |
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.
nit nit pick: overkill, 4 flag variables suffice #Resolved
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.
Maybe you can also support turning these on through environment variables, so we don't need to recompile.
In reply to: 82242030 [](ancestors = 82242030)
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.
Now we only have LogAPI, DebugJson and Error. DebugJson is enabled using --trace_debug_json and Error is enabled by default.
Seems like when we execute chakra_debug process object is not yet set so can't use that to get the environment variable. Will see if I can do something for dynamically enable/disable after the PR as a separate change.
In reply to: 82242030 [](ancestors = 82242030)
ScriptId: 0, | ||
ScriptName: 1, | ||
ScriptRegExp: 2 | ||
}; |
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.
Can these be messed up by user script? Should they be hidden/readonly somehow? #ByDesign
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.
Yes if you use vm.runInDebugContext and that's by design and same as v8
In reply to: 82244119 [](ancestors = 82244119)
this.objectPrototypeEval = undefined; | ||
} | ||
|
||
ExecutionState.prototype.ChangeToBreak = function() { |
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.
Why not use cool ES6 class for these #ByDesign
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.
Most of these is trying to mimic how its done in V8 (debug.js) and I would like to keep it as close as possible in terms of structure.
In reply to: 82246479 [](ancestors = 82246479)
|
||
if (found == true) { | ||
var scriptObj = element.GetProtocolObject(); | ||
if (includeSource == true) { |
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.
nit: if (found) ... if (includeSource) ... #Resolved
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.
Sorry I didn't understood what you mean here? found is used to track if a particular scriptid is requested and includeSource is tracking if additionally we need to include completed source of the script or not.
In reply to: 82246914 [](ancestors = 82246914)
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 think what @jianchun meant is instead of having if(found == true)
you could simply do if(found)
and vice versa for includeSource
. #Resolved
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.
@@ -140,23 +147,14 @@ bool V8::Initialize() { | |||
if (g_disposed) { | |||
return false; // Can no longer Initialize if Disposed | |||
} | |||
#ifndef NODE_ENGINE_CHAKRACORE |
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.
What's "node-chakra" / "node-uwp" debugging story after this change? Can this be merged to those branches? (Would this break VS debugging?) #Pending
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.
Disucssed with @digitalinfinity @aruneshchandra and for now we will go ahead with this break and understand why node-chakra/node-uwp needs to take changes from node-chakracore. If we need to support PDM based debugging will bring back in a separate change
In reply to: 82250358 [](ancestors = 82250358)
return result; | ||
} | ||
|
||
function CallHostFunction(fn) { |
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.
Nit: This looks very very similar to the previous function- can you combine? #WontFix
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.
CallHostFunction dumps the API output/result whereas CallHostFunctionNoLog doesn't, will keep it separate
In reply to: 83558470 [](ancestors = 83558470)
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.
nit: you could still extract the common code while keeping the functionality separate.
|
||
if (!globalObject.Debug) { | ||
Object.defineProperty(globalObject, 'Debug', { | ||
value: {}, enumerable: false, configurable: false, writable: false |
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.
The property descriptor keys are set to their default values- why not just do globalObject.Debug = {} #Resolved
var bpId = element.breakpointId; | ||
activeBreakpointList[bpId] = _breakpoints[bpId]; | ||
}); | ||
_breakpoints = activeBreakpointList; |
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.
Nit: can be a little more succinct doing _breakpoints = breakpoints.map(function(element, index, array) { return element.breakpointId; }) #WontFix
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.
Changing this is breaking from bp removal logic, will keep it this way to not break anything.
In reply to: 83558695 [](ancestors = 83558695)
static void SetChakraDebugObject(JsValueRef chakraDebugObject); | ||
private: | ||
static void InstallHostCallback(JsValueRef chakraDebugObject, | ||
const wchar_t *name, |
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.
Nit: indent function parameters #Resolved
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.
Left a bunch of nitpicky comments but you can fix after merging |
This change adds JavaScript debugging support in node-chakracore by using JsRT debugging apis added in chakracore release 1.3. A shim convert v8 debugging protocol messages to chakracore debugging apis and visa-versa. node-chakracore only expose the debugging protocol messages and doesn't shim all the apis which v8 provides, so it is only debuggable using tools which just relies on debugging protocol json and doesn't use internals of v8 debugging implementations. PR-URL: nodejs#126 Reviewed-By: Hitesh Kanwathirtha <hiteshk@microsoft.com> Reviewed-By: Jianchun Xu <Jianchun.Xu@microsoft.com> Reviewed-By: Kunal Pathak <Kunal.Pathak@microsoft.com> Reviewed-By: Oguz Bastemur <ogbastem@microsoft.com>
e3d2a58
to
99d6392
Compare
Yay! 🎉 🍾 🍰 |
Checklist
make -j4 test
(UNIX), orvcbuild test nosign
(Windows) passesAffected core subsystem(s)
chakrashim, node
Description of change
This change adds JavaScript debugging support in node-chakracore by using
JsRT debugging apis added in chakracore release 1.3. A shim convert v8
debugging protocol messages to chakracore debugging apis and visa-versa.
node-chakracore only expose the debugging protocol messages and doesn't
shim all the apis which v8 provides, so it is only debuggable using tools
which just relies on debugging protocol json and doesn't use internals
of v8 debugging implementations.
PR-URL: nodejs/node-chakracore#[To be filled]
Reviewed-By: [To be filled]