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

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

Open
dpogue opened this issue Jan 11, 2018 · 4 comments
Open

Comments

@dpogue
Copy link

dpogue commented Jan 11, 2018

  • 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
@MSLaguana
Copy link
Contributor

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.

@MSLaguana
Copy link
Contributor

See #391 for some more details.

@dpogue
Copy link
Author

dpogue commented Jan 11, 2018

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) 😅

@jackhorton
Copy link
Contributor

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

boingoing pushed a commit that referenced this issue Jan 18, 2018
As part of the readableState/writableState mega issue #445, this
removes all of the references to .length on those properties and
replaces them with a readableLength and writableLength getter.

See: nodejs/node#445
PR-URL: nodejs/node#12857
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
boingoing pushed a commit that referenced this issue Jan 19, 2018
As part of the readableState/writableState mega issue #445, this
removes all of the references to .length on those properties and
replaces them with a readableLength and writableLength getter.

See: nodejs/node#445
PR-URL: nodejs/node#12857
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants