At some point in the V8 upgrades, Live Edit started hard-crashing when calling the SetScriptSource() function. If you're running in an environment where you can see the error logs, you might see this:
#
# Fatal error in ../deps/v8/src/runtime/runtime-liveedit.cc, line 255
# Check failed: isolate->debug()->live_edit_enabled().
#
I use this functionality to monitor files for changes, and reload them into the running runtime where possible. It's a huge help during development, and obviously I don't use this in production. It's a bit like the Chrome Dev Tools, but for node JS, and you can use it with transpiling. The full code for the project is in on GitHub (including invoking the TypeScript compiler where necessary -- https://github.com/Frugality/v8-script-live-edit), but I have a pretty small sample I'll add below which demonstrates the issue:
function print() {
console.log(`Time = ${Date.now()}`);
}
setInterval(print, 100);
function print() {
console.log(`The Time Is Now ${Date.now()}`);
}
setInterval(print, 100);
const fs = require('fs');
const vm = require('vm');
const path = require('path');
function reloadScript(filename, contents) {
const Debug = vm.runInDebugContext('Debug');
let script = Debug.findScript(filename);
if (script) {
console.log(`Reloading ${filename}`);
let changes = new Array();
Debug.LiveEdit.SetScriptSource(script, contents, false, changes);
}
}
// Load script with the timer
const a = require('./a');
// replacement contents
const newContent = fs.readFileSync('./b.js', 'utf8');
function reloadOurScript() {
console.log('Attempting script reload');
let filename = path.join(process.cwd(), 'a.js');
reloadScript(filename, newContent);
}
setTimeout(reloadOurScript, 450)
I see that this functionality is being moved around a bit, so if there's some changes I need to make, I'd love to know. I did notice that Debug::SetScriptSource() is new in v9.0.0, but I'm not entirely sure how I would invoke that directly w/o using LiveEdit. Any help would be appreciated I would love to get this working again with a recent version of NodeJS
Thanks
-Courtland
Easily recreated in MAC. Failing with master as well. Trying to get a debug build to dig further.
reduced the recreate to:
require('vm').runInDebugContext('Debug').LiveEdit.SetScriptSource('a', 'b', false, 'c');
#0 v8::internal::Runtime_LiveEditCompareStrings (args_length=2, args_object=0xfffffffffffdc20,
isolate=0x1104b8090) at ../deps/v8/src/runtime/runtime-liveedit.cc:253
#1 0x07000000001bd3d4 in ?? ()
(gdb) p isolate->debug_.live_edit_enabled_
$5 = False
(gdb)
/cc @bnoordhuis (my capability ends here. :) )
The vm.runInDebugContext() method has be deprecated since v8.x, from the documentation:
Note: The debug context and object are intrinsically tied to V8's debugger implementation and may change (or even be removed) without prior warning.
Yep, doing that through the debug context no longer works. You can still do it through the inspector protocol: https://github.com/nodejs/node/blob/3d4d5e0c60f00693947c940b09249f3952bb0cdc/deps/v8/src/inspector/js_protocol.json#L615-L629
Hope that helps.
Ooh, the Inspector protocol looks great! I did notice that runInDebugContext() was marked deprecated in favor of inspector, however, the "Experimental" tag scared me away from using the inspector module. The single-debugger-client interface was also problematic for my use case, but it sounds like that'll be removed in the near future (https://developers.google.com/web/updates/2017/10/devtools-release-notes#multi-client).
Do you know if there's a way to access the inspector in-process? A little digging revealed "chrome.debugger" as the Browser version of this functionality. I'm attempting to trace through the implementation, but not coming up with too much so far. A little nudge in the right direction would help a lot!
Thanks!
const { Session } = require('inspector');
const sess = new Session();
sess.connect();
sess.post('Debugger.enable', (err, res) => { /* ... */ });
// etc.
Grep for Session in test/, there are a couple of tests you can use as a starting point.
Thanks so much for the help and pointer to the Session tests. I have a better understanding here of how the pieces work. The session interface looks ideal once multi client debugging is in (super new in Chrome 63, any idea when this might come to Node?) -- I normally run with a debugger already attached, which isn't currently supported and throws 'TypeError: Session is already attached". In the meantime my options look to be
Thanks again for the help!!
FWIW I ended up writing a native extension to flip the live_edit_enabled boolean to true. This gets me running through 8.9.1 at least. You can see the extension here: https://github.com/Frugality/v8-script-live-edit . I mostly use this for writing game-servers in node, where the amount of state can be quite large (making the edit/shutdown/startup/refresh cycle take a while), and I'm experimenting with code. It's... just magical to have your code update-on-the-fly 馃
This method doesn't work in 9.x.x, as the runInDebugContext() is since removed, and I'm still waiting for multi-client debugging to become available.
Most helpful comment
reduced the recreate to: