Skip to content
This repository was archived by the owner on Oct 15, 2020. It is now read-only.
This repository was archived by the owner on Oct 15, 2020. It is now read-only.

Segfault in node::loader::ModuleWrap::Link with --experimental-modules #445

@dpogue

Description

@dpogue
  • 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions