Skip to content

Commit 1dd8191

Browse files
GeoffreyBoothtargos
authored andcommitted
module: support multi-dot file extension
Support multi-dot file extensions like '.coffee.md' in Module.load. PR-URL: #23416 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
1 parent 8bffd90 commit 1dd8191

File tree

3 files changed

+111
-20
lines changed

3 files changed

+111
-20
lines changed

lib/internal/modules/cjs/loader.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,22 @@ function tryExtensions(p, exts, isMain) {
219219
return false;
220220
}
221221

222+
// find the longest (possibly multi-dot) extension registered in
223+
// Module._extensions
224+
function findLongestRegisteredExtension(filename) {
225+
const name = path.basename(filename);
226+
let currentExtension;
227+
let index;
228+
let startIndex = 0;
229+
while ((index = name.indexOf('.', startIndex)) !== -1) {
230+
startIndex = index + 1;
231+
if (index === 0) continue; // Skip dotfiles like .gitignore
232+
currentExtension = name.slice(index);
233+
if (Module._extensions[currentExtension]) return currentExtension;
234+
}
235+
return '.js';
236+
}
237+
222238
var warned = false;
223239
Module._findPath = function(request, paths, isMain) {
224240
if (path.isAbsolute(request)) {
@@ -600,8 +616,7 @@ Module.prototype.load = function(filename) {
600616
this.filename = filename;
601617
this.paths = Module._nodeModulePaths(path.dirname(filename));
602618

603-
var extension = path.extname(filename) || '.js';
604-
if (!Module._extensions[extension]) extension = '.js';
619+
var extension = findLongestRegisteredExtension(filename);
605620
Module._extensions[extension](this, filename);
606621
this.loaded = true;
607622

test/known_issues/test-module-deleted-extensions.js

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use strict';
2+
3+
// Refs: https://github.com/nodejs/node/issues/4778
4+
5+
const common = require('../common');
6+
const assert = require('assert');
7+
const fs = require('fs');
8+
const path = require('path');
9+
const Module = require('module');
10+
const tmpdir = require('../common/tmpdir');
11+
const file = path.join(tmpdir.path, 'test-extensions.foo.bar');
12+
const dotfile = path.join(tmpdir.path, '.bar');
13+
const dotfileWithExtension = path.join(tmpdir.path, '.foo.bar');
14+
15+
tmpdir.refresh();
16+
fs.writeFileSync(file, 'console.log(__filename);', 'utf8');
17+
fs.writeFileSync(dotfile, 'console.log(__filename);', 'utf8');
18+
fs.writeFileSync(dotfileWithExtension, 'console.log(__filename);', 'utf8');
19+
20+
{
21+
require.extensions['.bar'] = common.mustNotCall();
22+
require.extensions['.foo.bar'] = common.mustCall();
23+
const modulePath = path.join(tmpdir.path, 'test-extensions');
24+
require(modulePath);
25+
require(file);
26+
delete require.cache[file];
27+
delete require.extensions['.bar'];
28+
delete require.extensions['.foo.bar'];
29+
Module._pathCache = Object.create(null);
30+
}
31+
32+
{
33+
require.extensions['.foo.bar'] = common.mustCall();
34+
const modulePath = path.join(tmpdir.path, 'test-extensions');
35+
require(modulePath);
36+
assert.throws(
37+
() => require(`${modulePath}.foo`),
38+
new Error(`Cannot find module '${modulePath}.foo'`)
39+
);
40+
require(`${modulePath}.foo.bar`);
41+
delete require.cache[file];
42+
delete require.extensions['.foo.bar'];
43+
Module._pathCache = Object.create(null);
44+
}
45+
46+
{
47+
const modulePath = path.join(tmpdir.path, 'test-extensions');
48+
assert.throws(
49+
() => require(modulePath),
50+
new Error(`Cannot find module '${modulePath}'`)
51+
);
52+
delete require.cache[file];
53+
Module._pathCache = Object.create(null);
54+
}
55+
56+
{
57+
require.extensions['.bar'] = common.mustNotCall();
58+
require.extensions['.foo.bar'] = common.mustCall();
59+
const modulePath = path.join(tmpdir.path, 'test-extensions.foo');
60+
require(modulePath);
61+
delete require.cache[file];
62+
delete require.extensions['.bar'];
63+
delete require.extensions['.foo.bar'];
64+
Module._pathCache = Object.create(null);
65+
}
66+
67+
{
68+
require.extensions['.foo.bar'] = common.mustNotCall();
69+
const modulePath = path.join(tmpdir.path, 'test-extensions.foo');
70+
assert.throws(
71+
() => require(modulePath),
72+
new Error(`Cannot find module '${modulePath}'`)
73+
);
74+
delete require.extensions['.foo.bar'];
75+
Module._pathCache = Object.create(null);
76+
}
77+
78+
{
79+
require.extensions['.bar'] = common.mustNotCall();
80+
require(dotfile);
81+
delete require.cache[dotfile];
82+
delete require.extensions['.bar'];
83+
Module._pathCache = Object.create(null);
84+
}
85+
86+
{
87+
require.extensions['.bar'] = common.mustCall();
88+
require.extensions['.foo.bar'] = common.mustNotCall();
89+
require(dotfileWithExtension);
90+
delete require.cache[dotfileWithExtension];
91+
delete require.extensions['.bar'];
92+
delete require.extensions['.foo.bar'];
93+
Module._pathCache = Object.create(null);
94+
}

0 commit comments

Comments
 (0)