From 569ad0aa38245bb6a4155a54fccce47ffb97c0ca Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 9 Jun 2023 16:31:08 -0700 Subject: [PATCH] Re-enable support for default exports See #2008 --- CHANGELOG.md | 6 ++++++ tool/grind.dart | 38 ++++++++++++++++++++++++++++++++++++++ tool/grind/utils.dart | 20 ++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 747deb5d2..283e58b3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## 1.63.4 +### JavaScript API + +* Re-enable support for `import sass from 'sass'` when loading the package from + an ESM module. However, this syntax is now deprecated; ESM users should use + `import * as sass from 'sass'` instead. + ### Embedded Sass * Fix a race condition where closing standard input while requests are in-flight diff --git a/tool/grind.dart b/tool/grind.dart index 84bec47c6..95cd60a8b 100644 --- a/tool/grind.dart +++ b/tool/grind.dart @@ -101,6 +101,10 @@ void main(List args) { }; pkg.addAllTasks(); + + afterTask("pkg-npm-dev", _addDefaultExport); + afterTask("pkg-npm-release", _addDefaultExport); + grind(args); } @@ -243,3 +247,37 @@ dart run protoc_plugin "\$@" Platform.environment["PATH"]! })); } + +/// After building the NPM package, add default exports to +/// `build/npm/sass.node.mjs`. +/// +/// See sass/dart-sass#2008. +void _addDefaultExport() { + var buffer = StringBuffer(); +buffer.writeln(File("build/npm/sass.node.mjs").readAsStringSync()); + +buffer.writeln(""" +let printedDefaultExportDeprecation = false; +function defaultExportDeprecation() { + if (printedDefaultExportDeprecation) return; + printedDefaultExportDeprecation = true; + console.error( + "`import sass from 'sass'` is deprecated.\\n" + + "Please use `import * as sass from 'sass'` instead."); +} +"""); + +buffer.writeln("export default {"); +for (var export in pkg.jsEsmExports.value!) { + buffer.write(""" + get $export() { + defaultExportDeprecation(); + return _cliPkgExports.$export; + }, +"""); +} + +buffer.writeln("};"); + +File("build/npm/sass.node.mjs").writeAsStringSync(buffer.toString()); +} diff --git a/tool/grind/utils.dart b/tool/grind/utils.dart index 1135865ee..9d230cb0a 100644 --- a/tool/grind/utils.dart +++ b/tool/grind/utils.dart @@ -2,6 +2,7 @@ // MIT-style license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. +import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -9,6 +10,9 @@ import 'package:cli_pkg/cli_pkg.dart' as pkg; import 'package:grinder/grinder.dart'; import 'package:path/path.dart' as p; +// Work around the lack of google/grinder.dart#402. +import 'package:grinder/src/singleton.dart'; + /// Options for [run] that tell Git to commit using SassBot's name and email. final sassBotEnvironment = RunOptions(environment: { "GIT_AUTHOR_NAME": pkg.botName.value, @@ -75,3 +79,19 @@ String cloneOrCheckout(String url, String ref, {String? name}) { return path; } + +/// Registers [callback] to run after the task named [taskName]. +/// +/// This must be called after the base [taskName] is registered. +void afterTask(String taskName, FutureOr callback()) { + // This takes advantage of the fact that Grinder's task list is mutable to + // override the existing task with our new one. + var index = grinder.tasks.indexWhere((task) => task.name == taskName); + if (index == -1) fail("There is no task named $taskName."); + + var oldTask = grinder.tasks[index]; + grinder.tasks[index] = GrinderTask(taskName, description: oldTask.description, depends: oldTask.depends, taskFunction: (TaskArgs args) async { + await oldTask.execute(context, args); + await callback(); + }); +}