Segfault in node::loader::ModuleWrap::Link with --experimental-modules
- Version: v8.6.0
- Platform: Linux x64
Running node --experimental-modules test.mjs should print "Received QUX".
Instead it crashes with a segmentation fault.
This works in the v8 build of node, as well as in Chrome, Firefox, and Safari browsers. Note that it also fails in the Microsoft Edge browser, as reported here
Test Files
test.mjs
import { Event, EventTarget } from './event_target.mjs';
class Foo extends EventTarget { }
let f = new Foo();
f.addEventListener('qux', () => console.log('Received QUX'));
let e = new Event('qux');
f.dispatchEvent(e);
event_target.mjs
const ctx = (typeof global === 'object' && global.global === global && global) || (typeof self === 'object' && self.self === self && self);
let EventObject = ctx.Event;
if (!EventObject) {
EventObject = function(typeArg) {
this.type = typeArg;
};
}
let CustomEventObject = ctx.CustomEvent;
if (!CustomEventObject) {
CustomEventObject = class extends EventObject {
constructor(typeArg, opts) {
super(typeArg);
this.detail = opts.detail;
}
};
}
let EventBase = ctx.EventTarget;
try {
new EventBase();
} catch(e) {
const eventData = new WeakMap();
EventBase = class {
constructor() {
eventData.set(this, Object.create(null));
}
addEventListener(type, listener, options) {
const data = eventData.get(this);
const listeners = data[type] || (data[type] = []);
if (listener && !listeners.some(info => info.listener === listener)) {
listeners.push({target: this, listener, options});
}
}
removeEventListener(type, listener, options) {
const data = eventData.get(this);
const listeners = data[type] || Array(1);
for (let i = listeners.length - 1; i >= 0; --i) {
if (listeners[i] && listeners[i].listener === listener) {
listeners.splice(i, 1);
break;
}
}
}
dispatchEvent(evt) {
const data = eventData.get(this);
const listeners = data[evt.type] || [];
Object.defineProperty(evt, 'currentTarget', { configurable: true, value: this });
Object.defineProperty(evt, 'target', { configurable: true, value: this });
listeners.forEach(info => {
const options = info.options;
if (typeof options === 'object' && options.once) {
this.removeEventListener(evt.type, info.listener, info.options);
}
if (typeof info.listener === 'function') {
info.listener.call(info.target, evt);
} else {
info.listener.handleEvent(evt);
}
});
delete evt.currentTarget;
delete evt.target;
return !evt.defaultPrevented;
}
};
}
export { EventObject as Event, CustomEventObject as CustomEvent, EventBase as EventTarget };
gdb backtrace
Unfortunately no debugging symbols
(gdb) bt
#0 0x00000000009babcd in node::loader::ModuleWrap::Link(v8::FunctionCallbackInfo<v8::Value> const&) ()
#1 0x0000000000933051 in v8::FunctionCallbackData::FunctionInvoked(void*, bool, void**, unsigned short, void*) ()
#2 0x0000000000cbc081 in Js::JavascriptExternalFunction::StdCallExternalFunctionThunk(Js::RecyclableObject*, Js::CallInfo, ...) ()
#3 0x00000000014a70ee in amd64_CallFunction ()
#4 0x000000000110ff7d in void Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallIWithICIndex<Js::LayoutSizePolicy<(Js::LayoutSize)0> > > >(Js::OpLayoutDynamicProfile<Js::OpLayoutT_CallIWithICIndex<Js::LayoutSizePolicy<(Js::LayoutSize)0> > > const*, Js::RecyclableObject*, unsigned int, Js::AuxArray<unsigned int> const*) ()
#5 0x0000000000bb854c in Js::InterpreterStackFrame::ProcessUnprofiled() ()
#6 0x0000000000baa3bf in Js::InterpreterStackFrame::Process() ()
#7 0x0000000000ba97b5 in Js::InterpreterStackFrame::InterpreterHelper(Js::ScriptFunction*, Js::ArgumentReader, void*, void*, Js::InterpreterStackFrame::AsmJsReturnStruct*) ()
#8 0x0000000000ba8f37 in Js::InterpreterStackFrame::InterpreterThunk(Js::JavascriptCallStackLayout*) ()
#9 0x00007ff7f28d04f2 in ?? ()
#10 0x00007fffffffa440 in ?? ()
#11 0x00000000014a70ee in amd64_CallFunction ()
Backtrace stopped: frame did not save the PC
Thanks for reporting this @dpogue; ChakraCore doesn't provide all the hooks that node expects for es6 modules, so right now node-chakracore does not support them. We're working on adding support for what node expects in the near future.
See https://github.com/nodejs/node-chakracore/issues/391 for some more details.
Ah, thanks. I was hoping to use node-chakra to debug why it might be breaking in Edge, but it looks like it doesn't currently work in either of those cases (for unrelated reasons) 😅
For what its worth, ChakraCore has its own lightweight host, ch, that comes in the main ChakraCore repository. You might be able to use that, though note that it implements very little standard library outside of the ecmascript spec. You can download a ChakraCore release yourself, build it from source, or use JSVU alongside eshost-cli for always having easy access to the latest ChakraCore host in addition to V8, SpiderMonkey, and JavaScriptCore