I just tried pkging an application which injects JavaScript code into a Selenium-driven browser. The JS code/injection looks something like:
var browserCode = (something) => {
// Do various things... but for the sake of this contrived example, we'll change the <body>
document.body.innerHTML = something
}
var error = await webdriverInstance.executeAsyncScript(`
var __selenium_callback__ = arguments[arguments.length - 1]
try {
(
${browserCode.toString()}
)(
"${someValue}"
)
__selenium_callback__(null)
} catch (error) {
__selenium_callback__(error)
}
`);
if (error) {
throw new Error(error.message);
}
This yields a SyntaxError, as the injected code resembles something like:
var __selenium_callback__ = arguments[arguments.length - 1]
try {
(
[native code]
)(
"hello world"
)
__selenium_callback__(null)
} catch (error) {
__selenium_callback__(error)
}
This seems very related to https://github.com/zeit/pkg/issues/62, but it's not exclusively caused by calling Class#toString().
Looks like this is intentional, based on the updated spec: https://tc39.github.io/Function-prototype-toString-revision/#proposal-sec-function.prototype.tostring.
Closing for now.
I misread the spec. This is still an issue.
@stephenmathieson is there a workaround for this?
Just did a quick test:
test.js file:
const aFunction = () => 'Hello World';
console.log(typeof aFunction);
console.log(aFunction);
console.log(aFunction());
console.log(aFunction.toString());
console.log('end');
Return with node test.js:
[Function: aFunction]
Hello World
() => 'Hello World'
end
After running pkg:
pkg --targets node12-macos-x64 test.js
./test
[Function: aFunction]
Hello World
function aFunction() { [native code] }
end
As you can see with pkg Function.prototype.toString() returns
function aFunction() { [native code] } instead of the actual function.
CC: @igorklopov
My workaround was to not .toString() functions. I was not able to get this to work otherwise.
@igorklopov, others, is there a workaround for this? I'm trying to run https://github.com/microsoft/playwright and it heavily relies on function.toString().
If source code is stripped while packaging, then toString has nothing to show, that's why [native code]. But if you force pkg to leave source code for that js file, then toString will likely work as in node.js environment. For example --public option leaves source code of most js files intact. Also you can use any kind of config (package.json or something.json with -c something.json) and specify something like
{
"pkg": {
"assets": [
"file-to-leave-sources-in-executable.js"
]
}
}
Awesome, thanks @igorklopov , worked like a charm!