Skip to content

Commit c175210

Browse files
committed
[meta.load] Add support for meta.load() and related features
1 parent da84fb5 commit c175210

26 files changed

Lines changed: 628 additions & 284 deletions

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
## 1.105.0
2+
3+
* Add support for first-class modules. These can be accessed using the new
4+
`meta.load()` and `meta.get-module()` functions, and may be passed as the
5+
`$module` argument to numerous eisting `sass:meta` functions.
6+
7+
* Add the `meta.css()` mixin, which includes CSS from a first-class module.
8+
9+
### JS API
10+
11+
* Add a `SassModule` class and a corresponding `Value.assertModule()` method.
12+
13+
### Dart API
14+
15+
* Add a `SassModule` class and a corresponding `Value.assertModule()` method.
16+
117
## 1.104.1
218

319
* Fix a bug where loud comments before `@use` rules could be emitted multiple

lib/src/async_environment.dart

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ final class AsyncEnvironment {
438438
/// Throws a [SassScriptException] if there is no module named [namespace], or
439439
/// if multiple global modules expose variables named [name].
440440
Value? getVariable(String name, {String? namespace}) {
441-
if (namespace != null) return _getModule(namespace).variables[name];
441+
if (namespace != null) return getModule(namespace).variables[name];
442442

443443
if (_lastVariableName == name) {
444444
return _variables[_lastVariableIndex!][name] ??
@@ -477,7 +477,7 @@ final class AsyncEnvironment {
477477
/// required, since some nodes need to do real work to manufacture a source
478478
/// span.
479479
AstNode? getVariableNode(String name, {String? namespace}) {
480-
if (namespace != null) return _getModule(namespace).variableNodes[name];
480+
if (namespace != null) return getModule(namespace).variableNodes[name];
481481

482482
if (_lastVariableName == name) {
483483
return _variableNodes[_lastVariableIndex!][name] ??
@@ -526,7 +526,7 @@ final class AsyncEnvironment {
526526
/// if multiple global modules expose functions named [name].
527527
bool globalVariableExists(String name, {String? namespace}) {
528528
if (namespace != null) {
529-
return _getModule(namespace).variables.containsKey(name);
529+
return getModule(namespace).variables.containsKey(name);
530530
}
531531
if (_variables.first.containsKey(name)) return true;
532532
return _getVariableFromGlobalModule(name) != null;
@@ -567,7 +567,7 @@ final class AsyncEnvironment {
567567
bool global = false,
568568
}) {
569569
if (namespace != null) {
570-
_getModule(namespace).setVariable(name, value, nodeWithSpan);
570+
getModule(namespace).setVariable(name, value, nodeWithSpan);
571571
return;
572572
}
573573

@@ -663,7 +663,7 @@ final class AsyncEnvironment {
663663
/// Throws a [SassScriptException] if there is no module named [namespace], or
664664
/// if multiple global modules expose functions named [name].
665665
AsyncCallable? getFunction(String name, {String? namespace}) {
666-
if (namespace != null) return _getModule(namespace).functions[name];
666+
if (namespace != null) return getModule(namespace).functions[name];
667667

668668
if (_functionIndices[name] case var index?) {
669669
return _functions[index][name] ?? _getFunctionFromGlobalModule(name);
@@ -710,7 +710,7 @@ final class AsyncEnvironment {
710710
/// Throws a [SassScriptException] if there is no module named [namespace], or
711711
/// if multiple global modules expose mixins named [name].
712712
AsyncCallable? getMixin(String name, {String? namespace}) {
713-
if (namespace != null) return _getModule(namespace).mixins[name];
713+
if (namespace != null) return getModule(namespace).mixins[name];
714714

715715
if (_mixinIndices[name] case var index?) {
716716
return _mixins[index][name] ?? _getMixinFromGlobalModule(name);
@@ -891,10 +891,10 @@ final class AsyncEnvironment {
891891

892892
/// Returns the module with the given [namespace], or throws a
893893
/// [SassScriptException] if none exists.
894-
Module _getModule(String namespace) {
894+
Module getModule(String namespace) {
895895
if (_modules[namespace] case var module?) return module;
896896
throw SassScriptException(
897-
'There is no module with the namespace "$namespace".',
897+
'There is no module with namespace "$namespace".',
898898
);
899899
}
900900

lib/src/embedded/compilation_dispatcher.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:sass/src/importer/node_package.dart' as npi;
1717
import '../logger.dart';
1818
import '../value/function.dart';
1919
import '../value/mixin.dart';
20+
import '../value/module.dart';
2021
import 'embedded_sass.pb.dart';
2122
import 'opaque_registry.dart';
2223
import 'host_callable.dart';
@@ -108,6 +109,7 @@ final class CompilationDispatcher(
108109
) {
109110
var functions = OpaqueRegistry<SassFunction>();
110111
var mixins = OpaqueRegistry<SassMixin>();
112+
var modules = OpaqueRegistry<SassModule>();
111113

112114
sass.OutputStyle style = request.style == OutputStyle.COMPRESSED
113115
? .compressed
@@ -161,7 +163,8 @@ final class CompilationDispatcher(
161163
);
162164

163165
var globalFunctions = request.globalFunctions.map(
164-
(signature) => hostCallable(this, functions, mixins, signature),
166+
(signature) =>
167+
hostCallable(this, functions, mixins, modules, signature),
165168
);
166169

167170
late sass.CompileResult result;

lib/src/embedded/host_callable.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import '../callable.dart';
66
import '../exception.dart';
77
import '../value/function.dart';
88
import '../value/mixin.dart';
9+
import '../value/module.dart';
910
import 'compilation_dispatcher.dart';
1011
import 'embedded_sass.pb.dart';
1112
import 'opaque_registry.dart';
@@ -24,12 +25,13 @@ Callable hostCallable(
2425
CompilationDispatcher dispatcher,
2526
OpaqueRegistry<SassFunction> functions,
2627
OpaqueRegistry<SassMixin> mixins,
28+
OpaqueRegistry<SassModule> modules,
2729
String signature, {
2830
int? id,
2931
}) {
3032
late Callable callable;
3133
callable = Callable.fromSignature(signature, (arguments) {
32-
var protofier = Protofier(dispatcher, functions, mixins);
34+
var protofier = Protofier(dispatcher, functions, mixins, modules);
3335
var request = OutboundMessage_FunctionCallRequest()
3436
..arguments.addAll([
3537
for (var argument in arguments) protofier.protofy(argument),

lib/src/embedded/protofier.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ final class Protofier(
2525

2626
/// The IDs of first-class mixins.
2727
final OpaqueRegistry<SassMixin> _mixins,
28+
29+
/// The IDs of first-class modules.
30+
final OpaqueRegistry<SassModule> _modules,
2831
) {
2932
/// Any argument lists transitively contained in [value].
3033
///
@@ -93,6 +96,8 @@ final class Protofier(
9396
);
9497
case SassMixin():
9598
result.compilerMixin = Value_CompilerMixin(id: _mixins.getId(value));
99+
case SassModule():
100+
result.compilerModule = Value_CompilerModule(id: _modules.getId(value));
96101
case sassTrue:
97102
result.singleton = SingletonValue.TRUE;
98103
case sassFalse:
@@ -304,6 +309,7 @@ final class Protofier(
304309
_dispatcher,
305310
_functions,
306311
_mixins,
312+
_modules,
307313
value.hostFunction.signature,
308314
id: value.hostFunction.id,
309315
),
@@ -316,6 +322,13 @@ final class Protofier(
316322
"CompilerMixin.id $id doesn't match any known mixins",
317323
);
318324

325+
case Value_Value.compilerModule:
326+
var id = value.compilerModule.id;
327+
if (_modules[id] case var module?) return module;
328+
throw paramsError(
329+
"CompilerModule.id $id doesn't match any known modules.",
330+
);
331+
319332
case Value_Value.calculation:
320333
return _deprotofyCalculation(value.calculation);
321334

lib/src/environment.dart

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_environment.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: 6d84948495bad10a2416f6d51fd568322523c5e6
8+
// Checksum: 7b9b411c85ad6da89891b089912cc52c673fc801
99
//
1010
// ignore_for_file: unused_import
1111

@@ -449,7 +449,7 @@ final class Environment {
449449
/// Throws a [SassScriptException] if there is no module named [namespace], or
450450
/// if multiple global modules expose variables named [name].
451451
Value? getVariable(String name, {String? namespace}) {
452-
if (namespace != null) return _getModule(namespace).variables[name];
452+
if (namespace != null) return getModule(namespace).variables[name];
453453

454454
if (_lastVariableName == name) {
455455
return _variables[_lastVariableIndex!][name] ??
@@ -488,7 +488,7 @@ final class Environment {
488488
/// required, since some nodes need to do real work to manufacture a source
489489
/// span.
490490
AstNode? getVariableNode(String name, {String? namespace}) {
491-
if (namespace != null) return _getModule(namespace).variableNodes[name];
491+
if (namespace != null) return getModule(namespace).variableNodes[name];
492492

493493
if (_lastVariableName == name) {
494494
return _variableNodes[_lastVariableIndex!][name] ??
@@ -537,7 +537,7 @@ final class Environment {
537537
/// if multiple global modules expose functions named [name].
538538
bool globalVariableExists(String name, {String? namespace}) {
539539
if (namespace != null) {
540-
return _getModule(namespace).variables.containsKey(name);
540+
return getModule(namespace).variables.containsKey(name);
541541
}
542542
if (_variables.first.containsKey(name)) return true;
543543
return _getVariableFromGlobalModule(name) != null;
@@ -578,7 +578,7 @@ final class Environment {
578578
bool global = false,
579579
}) {
580580
if (namespace != null) {
581-
_getModule(namespace).setVariable(name, value, nodeWithSpan);
581+
getModule(namespace).setVariable(name, value, nodeWithSpan);
582582
return;
583583
}
584584

@@ -674,7 +674,7 @@ final class Environment {
674674
/// Throws a [SassScriptException] if there is no module named [namespace], or
675675
/// if multiple global modules expose functions named [name].
676676
Callable? getFunction(String name, {String? namespace}) {
677-
if (namespace != null) return _getModule(namespace).functions[name];
677+
if (namespace != null) return getModule(namespace).functions[name];
678678

679679
if (_functionIndices[name] case var index?) {
680680
return _functions[index][name] ?? _getFunctionFromGlobalModule(name);
@@ -721,7 +721,7 @@ final class Environment {
721721
/// Throws a [SassScriptException] if there is no module named [namespace], or
722722
/// if multiple global modules expose mixins named [name].
723723
Callable? getMixin(String name, {String? namespace}) {
724-
if (namespace != null) return _getModule(namespace).mixins[name];
724+
if (namespace != null) return getModule(namespace).mixins[name];
725725

726726
if (_mixinIndices[name] case var index?) {
727727
return _mixins[index][name] ?? _getMixinFromGlobalModule(name);
@@ -902,10 +902,10 @@ final class Environment {
902902

903903
/// Returns the module with the given [namespace], or throws a
904904
/// [SassScriptException] if none exists.
905-
Module<Callable> _getModule(String namespace) {
905+
Module<Callable> getModule(String namespace) {
906906
if (_modules[namespace] case var module?) return module;
907907
throw SassScriptException(
908-
'There is no module with the namespace "$namespace".',
908+
'There is no module with namespace "$namespace".',
909909
);
910910
}
911911

lib/src/functions/meta.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ final _shared = UnmodifiableListView([
6363
SassNumber() => "number",
6464
SassFunction() => "function",
6565
SassMixin() => "mixin",
66+
SassModule() => "module",
6667
SassCalculation() => "calculation",
6768
SassString() => "string",
6869
_ => throw "[BUG] Unknown value type ${arguments[0]}",

lib/src/js.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ void main() {
5050
exports.SassColor = colorClass;
5151
exports.SassFunction = functionClass;
5252
exports.SassMixin = mixinClass;
53+
exports.SassModule = moduleClass;
5354
exports.SassList = listClass;
5455
exports.SassMap = mapClass;
5556
exports.SassNumber = numberClass;

lib/src/js/exports.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Exports {
4040
external set SassColor(JSClass function);
4141
external set SassFunction(JSClass function);
4242
external set SassMixin(JSClass mixin);
43+
external set SassModule(JSClass mixin);
4344
external set SassList(JSClass function);
4445
external set SassMap(JSClass function);
4546
external set SassNumber(JSClass function);

lib/src/js/value.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export 'value/function.dart';
1616
export 'value/list.dart';
1717
export 'value/map.dart';
1818
export 'value/mixin.dart';
19+
export 'value/module.dart';
1920
export 'value/number.dart';
2021
export 'value/string.dart';
2122

@@ -44,6 +45,7 @@ final JSClass valueClass = () {
4445
'assertFunction': (Value self, [String? name]) => self.assertFunction(name),
4546
'assertMap': (Value self, [String? name]) => self.assertMap(name),
4647
'assertMixin': (Value self, [String? name]) => self.assertMixin(name),
48+
'assertModule': (Value self, [String? name]) => self.assertModule(name),
4749
'assertNumber': (Value self, [String? name]) => self.assertNumber(name),
4850
'assertString': (Value self, [String? name]) => self.assertString(name),
4951
'tryMap': (Value self) => self.tryMap(),

0 commit comments

Comments
 (0)