diff --git a/lib/ConsoleAgent.js b/lib/ConsoleAgent.js index 900c473..66d0d5e 100644 --- a/lib/ConsoleAgent.js +++ b/lib/ConsoleAgent.js @@ -11,14 +11,14 @@ class ConsoleAgent extends Agent { constructor(options) { super(options); this.printCommand = 'print'; - + this.cpOptions = {}; // Promise for the child process created by the most recent invocation of // `evalScript` this._cp = null; } - createChildProcess(args = []) { - return cp.spawn(this.hostPath, this.args.concat(args)); + createChildProcess(args = [], options = {}) { + return cp.spawn(this.hostPath, this.args.concat(args), options); } receiveOut(cp, str) { diff --git a/lib/agents/jsc.js b/lib/agents/jsc.js index 9c12028..73c1f09 100644 --- a/lib/agents/jsc.js +++ b/lib/agents/jsc.js @@ -1,12 +1,16 @@ 'use strict'; const fs = require('fs'); +const path = require('path'); +const isSymlink = require('is-symlink'); const inception = require('../inception'); const runtimePath = require('../runtimePath'); const ConsoleAgent = require('../ConsoleAgent'); const errorRe = /(?:.*?): (\w+)(?:: (.*))?(?:\r?\nat[^\n]*)?(\r?\n.*@(\[native code\]|(?:.*:\d+:\d+)))*\r?\n/; +let DYLD_FRAMEWORK_PATH = process.env.DYLD_FRAMEWORK_PATH; + // JSC stack frame format: // StackFrames: StackFrame+ // StackFrame: FunctionFrame | NativeFrame | EvalMarker @@ -60,6 +64,56 @@ function parseStack(stackStr) { } class JSCAgent extends ConsoleAgent { + constructor(...args) { + super(...args); + + /* + See: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/dyld.1.html + + This is frustrating, but necessary. DYLD_FRAMEWORK_PATH won't appear + in process.env when node.js scripts are executed as binaries, + ie. have a /usr/bin/env she-bang, because DYLD_* vars are excluded from env output + + $ export DYLD_FRAMEWORK_PATH="foo" + $ node -pe process.env.DYLD_FRAMEWORK_PATH + foo + $ env | grep "DYLD_FRAMEWORK_PATH" + (not found, nothing prints) + + + Still not convinced? The following code shows that even WebKit's own run-jsc + script must do this dance to ensure that DYLD_FRAMEWORK_PATH is set with the + correct path for executing built-from-source jsc: + + - https://github.com/WebKit/webkit/blob/026ee0438dd6c9cff16c27eb7ce9eaed2b43491c/Tools/Scripts/run-jsc#L58-L61 + - https://github.com/WebKit/webkit/blob/026ee0438dd6c9cff16c27eb7ce9eaed2b43491c/Tools/Scripts/webkitdirs.pm#L786-L789 + - https://github.com/WebKit/webkit/blob/026ee0438dd6c9cff16c27eb7ce9eaed2b43491c/Tools/Scripts/webkitdirs.pm#L770-L784 + */ + + if (DYLD_FRAMEWORK_PATH === undefined) { + if (isSymlink.sync(this.hostPath)) { + let linked = fs.readlinkSync(this.hostPath); + if (linked.includes('WebKit/WebKitBuild')) { + DYLD_FRAMEWORK_PATH = path.dirname(linked); + } + } else { + if (this.hostPath.includes('WebKit/WebKitBuild')) { + DYLD_FRAMEWORK_PATH = path.dirname(this.hostPath); + } + } + } + + this.cpOptions = { + env: { + DYLD_FRAMEWORK_PATH + } + }; + } + + createChildProcess(args = []) { + return super.createChildProcess(args, this.cpOptions); + } + parseError(str) { const match = str.match(errorRe); diff --git a/package.json b/package.json index 2ebde18..e64cbdf 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "error-stack-parser": "^1.3.3", + "is-symlink": "^0.1.1", "selenium-webdriver": "^3.4.0", "server-destroy": "^1.0.1", "socket.io": "^1.3.7",