Skip to content

Commit

Permalink
add support for loading loaders via import()
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Jul 3, 2020
1 parent 40c8e4f commit 4f91458
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ node_js:
- "6"
- "8"
- "10"
- "12"
- "14"
- node
script: npm run travis

Expand Down
3 changes: 2 additions & 1 deletion lib/LoaderRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ function createLoaderObject(loader) {
obj.ident = undefined;
} else {
if(!value.loader)
throw new Error("request should be a string or object with loader and object (" + JSON.stringify(value) + ")");
throw new Error("request should be a string or object with loader and options (" + JSON.stringify(value) + ")");
obj.path = value.loader;
obj.fragment = value.fragment || "";
obj.type = value.type;
obj.options = value.options;
obj.ident = value.ident;
if(obj.options === null)
Expand Down
49 changes: 34 additions & 15 deletions lib/loadLoader.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,42 @@
var LoaderLoadingError = require("./LoaderLoadingError");
var url;

module.exports = function loadLoader(loader, callback) {
try {
var module = require(loader.path);
} catch(e) {
// it is possible for node to choke on a require if the FD descriptor
// limit has been reached. give it a chance to recover.
if(e instanceof Error && e.code === "EMFILE") {
var retry = loadLoader.bind(null, loader, callback);
if(typeof setImmediate === "function") {
// node >= 0.9.0
return setImmediate(retry);
} else {
// node < 0.9.0
return process.nextTick(retry);
if(loader.type === "module") {

This comment has been minimized.

Copy link
@ogonkov

ogonkov Jul 9, 2020

How to mark loader with type module?

This comment has been minimized.

Copy link
@sokra

sokra Jul 9, 2020

Author Member

Not yet possible in webpack, but it will get this info from the package.json, where you put "type": "module"

This comment has been minimized.

Copy link
@ogonkov

ogonkov Jul 10, 2020

Didn't work for local install. I have loader folder with loader package, and loader-test, with webpack config that points to loader via path.resolve('../loader'), and it is not recognized as "module", while node is doing so (it emits warning that loader should be imported because nearest package.json have type: module). Webpack @ 5.0.0-beta.22

This comment has been minimized.

Copy link
@sokra

sokra Jul 10, 2020

Author Member

Yes I said:

Not yet possible in webpack,

This comment has been minimized.

Copy link
@ogonkov

ogonkov Jul 10, 2020

Oh, okay, sorry. Looking forward for that feature.

try {
if(url === undefined) url = require("url");
var loaderUrl = url.pathToFileURL(loader.path);
var modulePromise = eval("import(" + JSON.stringify(loaderUrl.toString()) + ")");
modulePromise.then(function(module) {
handleResult(loader, module, callback);
}, callback);
return;
} catch(e) {
callback(e);
}
} else {
try {
var module = require(loader.path);
} catch(e) {
// it is possible for node to choke on a require if the FD descriptor
// limit has been reached. give it a chance to recover.
if(e instanceof Error && e.code === "EMFILE") {
var retry = loadLoader.bind(null, loader, callback);
if(typeof setImmediate === "function") {
// node >= 0.9.0
return setImmediate(retry);
} else {
// node < 0.9.0
return process.nextTick(retry);
}
}
return callback(e);
}
return callback(e);
return handleResult(loader, module, callback);
}
};

function handleResult(loader, module, callback) {
if(typeof module !== "function" && typeof module !== "object") {
return callback(new LoaderLoadingError(
"Module '" + loader.path + "' is not a loader (export function or es6 module)"
Expand All @@ -32,4 +51,4 @@ module.exports = function loadLoader(loader, callback) {
));
}
callback();
};
}
3 changes: 3 additions & 0 deletions test/fixtures/esm-loader.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function(source) {
return source + "-esm";
};
22 changes: 22 additions & 0 deletions test/runLoaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,28 @@ describe("runLoaders", function() {
});
delete global.System;
});
if(+process.versions.modules >= 83) {
it("should load a loader using import()", function(done) {
runLoaders({
resource: path.resolve(fixtures, "resource.bin"),
loaders: [
{
loader: path.resolve(fixtures, "esm-loader.mjs"),
type: "module"
}
]
}, function(err, result) {
if(err) return done(err);
result.result.should.be.eql(["resource-esm"]);
result.cacheable.should.be.eql(true);
result.fileDependencies.should.be.eql([
path.resolve(fixtures, "resource.bin")
]);
result.contextDependencies.should.be.eql([]);
done();
});
});
}
describe("getContext", function() {
var TESTS = [
["/", "/"],
Expand Down

0 comments on commit 4f91458

Please sign in to comment.