Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
aad55d8
Add lively.context inspector runtime
merryman Jun 2, 2026
3a1cb94
Add NW inspector capture service
merryman Jun 2, 2026
cf5a905
Add Lively debugger UI
merryman Jun 2, 2026
888c144
Fix Node 25 mocha-es6 bootstrap
merryman Jun 4, 2026
2a4371f
Fix Lively debugger capture compatibility
merryman Jun 4, 2026
d8ca9c2
Fix context rewriter compatibility tests
merryman Jun 4, 2026
1509ba0
Fix lively.ast CI assertions
merryman Jun 4, 2026
90031f1
Fix remaining CI test compatibility
merryman Jun 4, 2026
b7b7759
Improve CI test error annotations
merryman Jun 4, 2026
c2db6d1
Load repository packages in CI test runner
merryman Jun 4, 2026
dbf7110
Remove context test shallow plugin dependency
merryman Jun 4, 2026
ba0469d
Annotate CI test assertion failures
merryman Jun 4, 2026
e5c8239
Provide legacy Path global for context continuations
merryman Jun 4, 2026
44ad19e
Stabilize context interpreter assertions
merryman Jun 4, 2026
2085508
🛠️🗺️👔: fix browser test runtime loading
merryman Jun 11, 2026
f935013
📦: include inspector service in desktop bundle
merryman Jun 11, 2026
df29c5a
🗺️📦: avoid debugger freezes in nw inspector
merryman Jun 11, 2026
c47fac6
🗺️📦: trigger inspector halts without debugger statement
merryman Jun 12, 2026
3a59f31
🗺️📦: use exception unwind for inspector debugger
merryman Jun 12, 2026
2236b2e
🛠️: install puppeteer browser on cold setup
merryman Jun 12, 2026
bed49e2
🗺️: update inspector halt runtime tests
merryman Jun 12, 2026
4b71dae
📦: defer inspector service until page load
merryman Jun 12, 2026
4f0bfdf
🗺️🧰📦: add inspector backed debugger stepping
merryman Jun 12, 2026
681065a
🧰📦: add debugger workspace and source maps
merryman Jun 13, 2026
e2aa482
📦: fail freezer build if node builtins leak into browser bundle
merryman Jun 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ then
exit
fi

section "Installing Puppeteer browser"
step "Preparing Chrome for headless tests..."
node "$(node -p "require.resolve('puppeteer/install.mjs')")" || exit 1
node <<'NODE' || exit 1
const fs = require('fs');
const puppeteer = require('puppeteer');
const executable = puppeteer.executablePath();
if (!fs.existsSync(executable)) {
throw new Error(`Puppeteer browser executable does not exist: ${executable}`);
}
console.log(` Puppeteer Chrome ready at ${executable}`);
NODE

section "Building SWC plugin"
if ! rustup target list --installed | grep -q "^wasm32-wasip1$"; then
step "Adding Rust target wasm32-wasip1..."
Expand Down
54 changes: 53 additions & 1 deletion lively.app/desktop/inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,63 @@
return window.confirm([title, message].filter(Boolean).join('\n\n'));
}

const desktop = window.livelyDesktop || {};
const desktopDebugger = desktop.debugger || {};
const debuggerState = window.__LIVELY_DESKTOP_DEBUGGER__ || (window.__LIVELY_DESKTOP_DEBUGGER__ = {
armedHalt: null,
captures: [],
serviceAttached: !!desktopDebugger.inspectorServiceAttached
});
if (desktopDebugger.inspectorServiceAttached) debuggerState.serviceAttached = true;

function armHalt (capture) {
if (!debuggerState.serviceAttached) return false;
debuggerState.armedHalt = {
captureId: capture && capture.captureId,
reason: capture && capture.reason || 'halt',
armedAt: Date.now()
};
return true;
}

function consumeArmedHalt () {
const capture = debuggerState.armedHalt;
debuggerState.armedHalt = null;
return capture;
}

function isAvailable () {
return !!debuggerState.serviceAttached;
}

function setServiceAttached (attached) {
debuggerState.serviceAttached = !!attached;
return debuggerState.serviceAttached;
}

function deliverCapture (descriptor) {
debuggerState.captures.push(descriptor);
debuggerState.lastCapture = descriptor;
try {
window.dispatchEvent(new CustomEvent('lively-desktop-debugger-capture', { detail: descriptor }));
} catch (_) {}
return true;
}

window.livelyDesktop = {
...desktop,
navigateToDashboard: navigateToDashboard,
showDevTools: showDevTools,
showDesktopMessage: showDesktopMessage,
confirmDesktopAction: confirmDesktopAction
confirmDesktopAction: confirmDesktopAction,
debugger: {
...desktopDebugger,
armHalt: desktopDebugger.armHalt || armHalt,
consumeArmedHalt: desktopDebugger.consumeArmedHalt || consumeArmedHalt,
isAvailable: desktopDebugger.isAvailable || isAvailable,
setServiceAttached: desktopDebugger.setServiceAttached || setServiceAttached,
deliverCapture: desktopDebugger.deliverCapture || deliverCapture
}
};

// Keyboard shortcut: Cmd/Ctrl + Shift + D → Dashboard.
Expand Down
40 changes: 40 additions & 0 deletions lively.app/desktop/inspector-service-runner.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Runs the CDP-backed inspector service outside NW.js's renderer isolate.
//
// The renderer pauses briefly when lively.context throws its halt unwind
// exception. This plain Node process handles the CDP event, captures the
// paused stack, then resumes the renderer so normal exception unwinding can
// return control to the Lively UI.

const { createInspectorService } = require('./inspector-service.cjs');

function parseArgs () {
const args = {};
for (const arg of process.argv.slice(2)) {
const match = arg.match(/^--([^=]+)=(.*)$/);
if (match) args[match[1]] = match[2];
}
return args;
}

const args = parseArgs();
const cdpPort = Number(args.cdpPort || process.env.LIVELY_APP_CDP_PORT || 9222);
const service = createInspectorService({
cdpPort: Number.isFinite(cdpPort) && cdpPort > 0 ? cdpPort : 9222,
log: msg => console.log(msg)
});

function stop () {
try { service.stop(); } catch (_) {}
process.exit(0);
}

process.on('SIGTERM', stop);
process.on('SIGINT', stop);

service.start().then(() => {
// Keep the helper alive; the parent-death watchdog is preloaded by node-main.
setInterval(() => {}, 1 << 30);
}).catch(err => {
console.error(err && (err.stack || err.message) || String(err));
process.exit(1);
});
Loading
Loading