Skip to content

Commit

Permalink
Properly handle new NodePackageImporter() with an ESM entrypoint (#…
Browse files Browse the repository at this point in the history
…2181)

Closes #2178
  • Loading branch information
nex3 committed Feb 21, 2024
1 parent 85a932f commit 6d66c43
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 15 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

* Export the `NodePackageImporter` class in ESM mode.

* Allow `NodePackageImporter` to locate a default directory even when the
entrypoint is an ESM module.

### Dart API

* Make passing a null argument to `NodePackageImporter()` a static error rather
than just a runtime error.

### Embedded Sass

* In the JS Embedded Host, properly install the musl Linux embedded compiler
Expand Down
8 changes: 2 additions & 6 deletions lib/src/importer/node_package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,8 @@ class NodePackageImporter extends Importer {
late final String _entryPointDirectory;

/// Creates a Node package importer with the associated entry point.
NodePackageImporter(String? entryPointDirectory) {
if (entryPointDirectory == null) {
throw "The Node package importer cannot determine an entry point "
"because `require.main.filename` is not defined. "
"Please provide an `entryPointDirectory` to the `NodePackageImporter`.";
} else if (isBrowser) {
NodePackageImporter(String entryPointDirectory) {
if (isBrowser) {
throw "The Node package importer cannot be used without a filesystem.";
}
_entryPointDirectory = p.absolute(entryPointDirectory);
Expand Down
13 changes: 8 additions & 5 deletions lib/src/js/compile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,13 @@ List<AsyncCallable> _parseFunctions(Object? functions, {bool asynch = false}) {
final JSClass nodePackageImporterClass = () {
var jsClass = createJSClass(
'sass.NodePackageImporter',
(Object self, [String? entryPointDirectory]) => NodePackageImporter(
entryPointDirectory ??
(requireMainFilename != null
? p.dirname(requireMainFilename!)
: null)));
(Object self, [String? entrypointDirectory]) => NodePackageImporter(
switch ((entrypointDirectory, entrypointFilename)) {
((var directory?, _)) => directory,
(_, var filename?) => p.dirname(filename),
_ => throw "The Node package importer cannot determine an entry "
"point because `require.main.filename` is not defined. Please "
"provide an `entryPointDirectory` to the `NodePackageImporter`."
}));
return jsClass;
}();
26 changes: 26 additions & 0 deletions lib/src/js/module.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2024 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:js/js.dart';

@JS('nodeModule')
external JSModule get module;

/// A Dart API for the [`node:module`] module.
///
/// [`node:module`]: https://nodejs.org/api/module.html#modules-nodemodule-api
@JS()
@anonymous
class JSModule {
/// See https://nodejs.org/api/module.html#modulecreaterequirefilename.
external JSModuleRequire createRequire(String filename);
}

/// A `require` function returned by `module.createRequire()`.
@JS()
@anonymous
class JSModuleRequire {
/// See https://nodejs.org/api/modules.html#requireresolverequest-options.
external String resolve(String filename);
}
25 changes: 21 additions & 4 deletions lib/src/js/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'dart:js_util';
import 'dart:typed_data';

import 'package:node_interop/js.dart';
import 'package:node_interop/node.dart' hide module;
import 'package:js/js.dart';
import 'package:js/js_util.dart';

Expand All @@ -14,6 +14,7 @@ import '../utils.dart';
import '../value.dart';
import 'array.dart';
import 'function.dart';
import 'module.dart';
import 'reflection.dart';
import 'url.dart';

Expand Down Expand Up @@ -234,6 +235,22 @@ Syntax parseSyntax(String? syntax) => switch (syntax) {
_ => jsThrow(JsError('Unknown syntax "$syntax".'))
};

/// The value of require.main.filename
@JS("require.main.filename")
external String? get requireMainFilename;
/// The path to the Node.js entrypoint, if one can be located.
String? get entrypointFilename {
if (_requireMain?.filename case var filename?) {
return filename;
} else if (process.argv case [_, String path]) {
return module.createRequire(path).resolve(path);
} else {
return null;
}
}

@JS("require.main")
external _RequireMain? get _requireMain;

@JS()
@anonymous
class _RequireMain {
external String? get filename;
}
2 changes: 2 additions & 0 deletions tool/grind.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ void main(List<String> args) {
pkg.JSRequire("chokidar", target: pkg.JSRequireTarget.cli),
pkg.JSRequire("readline", target: pkg.JSRequireTarget.cli),
pkg.JSRequire("fs", target: pkg.JSRequireTarget.node),
pkg.JSRequire("module",
target: pkg.JSRequireTarget.node, identifier: 'nodeModule'),
pkg.JSRequire("stream", target: pkg.JSRequireTarget.node),
pkg.JSRequire("util", target: pkg.JSRequireTarget.node),
];
Expand Down

0 comments on commit 6d66c43

Please sign in to comment.