node 8.5.0 Windows版でESMを実行しようとすると「AssertionError [ERR_ASSERTION]: An invalid error message key was used: ERR_INVALID_PROTOCOL.」がでる件

公開:2017-09-17 07:23
更新:2020-02-15 04:37
カテゴリ:es6 modules,.mjs,node,ESM

node.js 8.5.0でオプション付きでes modulesがサポートされた。なので試してみることにした。

テストプログラムは以下のような簡単なものである。

// test.mjs
import fs from 'fs';

const file = fs.readFileSync('./test.mjs','utf-8');
console.log(file);

これを--experimental-modules付きで実行する。

node --experimental-modules test.mjs

実行するとエラーが発生。

I:\pj\www\html\wwwmaker>node --experimental-modules commands\keywords.mjs
(node:5568) ExperimentalWarning: The ESM module loader is experimental.
{ AssertionError [ERR_ASSERTION]: An invalid error message key was used: ERR_INVALID_PROTOCOL.
    at message (internal/errors.js:70:3)
    at NodeError (internal/errors.js:29:13)
    at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
    at Loader.import (internal/loader/Loader.js:61:27)
    at Function.Module._load (module.js:462:27)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:201:16)
    at bootstrap_node.js:626:3
  generatedMessage: false,
  name: 'AssertionError [ERR_ASSERTION]',
  code: 'ERR_ASSERTION',
  actual: undefined,
  expected: true,
  operator: '==' }

むむ。さすがエクスペリメンタル。。早速バグか。。と思ってググると以下がヒット。

ESM Module: ERR_INVALID_PROTOCOL · Issue #15374 · nodejs/node

どうもWindows 10のファイルパスC:~file://c/~に変更できないからのようだ。

> const { resolve } = process.binding('module_wrap'); resolve('C:\\main.mjs', 'file://c/')

URL {
  href: 'c:\\main.mjs',
  origin: 'null',
  protocol: 'c:',
  username: '',
  password: '',
  host: '',
  hostname: '',
  port: '',
  pathname: '\\main.mjs',
  search: '',
  searchParams: URLSearchParams {},
  hash: '' }

上のように、プロトコルにc:が入ってしまい、これで「そんなプロトコルない!!」というエラーを返すようである。
ちなみにubuntu on windows (LSW)では正常に動作した。。

// ubuntu on windows

sfpg@computer:~$ node --experimental-modules ./test.mjs
(node:1094) ExperimentalWarning: The ESM module loader is experimental.
import fs from 'fs';

const file = fs.readFileSync('./test.mjs','utf-8');
console.log(file);

8.5.1では以下のようにエラーメッセージが変更されるようだ。nightly buildで確かめた。。

{ Error [ERR_INVALID_PROTOCOL]: Protocol "i:" not supported. Expected "file:"
    at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
    at Loader.import (internal/loader/Loader.js:61:27)
    at Function.Module._load (module.js:462:27)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:201:16)
    at bootstrap_node.js:626:3 [Symbol(code)]: 'ERR_INVALID_PROTOCOL' }

しかしこれで解決かというとそうではない。
import文をコメントアウトしてみる。都合全部コメントアウトになるけど。。

// test.mjs
// import fs from 'fs';

// const file = fs.readFileSync('./test.mjs','utf-8');
// console.log(file);

実行してみると、同じエラーが発生。。

I:\pj\www\html\wwwmaker>node --experimental-modules ./commands/test.mjs
(node:11876) ExperimentalWarning: The ESM module loader is experimental.
{ Error [ERR_INVALID_PROTOCOL]: Protocol "i:" not supported. Expected "file:"
    at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
    at Loader.import (internal/loader/Loader.js:61:27)
    at Function.Module._load (module.js:462:27)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:201:16)
    at bootstrap_node.js:626:3 [Symbol(code)]: 'ERR_INVALID_PROTOCOL' }

実行時に内部的にモジュールをロードしているのだろうと思うんだけど、それがコケてしまっているようだ。 なのでエラーメッセージの変更は根本的な解決ではない。

ちなみに先ほどのissueに、解決案が載っていた。

https://github.com/guybedford/node/commit/cc05513d398491f88421deb878935d096a278db2

これでいけそうな気もするけどね。。
気になるのはこの問題がエラーメッセージの変更だけでCloseになっていること。大丈夫かな。。

いずれにしろちょっと待ちだな。。

9:38 追記

node 9.0.0のnightly-build(v9.0.0-nightly20170916b0d3bec95c)で確認したら、Fixされていた。
とりあえずよかった。しかしこれって--experimental-modulesをつけるとかならず発生するので、テストすればすぐわかるようなものだけどね。

2017/09/30 追記

node 8.6.0でこの問題は解決した。

Bug修正部分のcommit
https://github.com/nodejs/node/commit/c005713d05

8.6.0 Change Log
https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V8.md#8.6.0