Skip to content

Commit d460b3e

Browse files
committed
[meta.load] Add support for first-class modules
1 parent aa4ed87 commit d460b3e

3 files changed

Lines changed: 83 additions & 0 deletions

File tree

lib/src/protofier.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
SassCalculation,
2727
} from './value/calculations';
2828
import {SassMixin} from './value/mixin';
29+
import {SassModule} from './value/module';
2930

3031
/**
3132
* A class that converts [Value] objects into protobufs.
@@ -132,6 +133,14 @@ export class Protofier {
132133
}
133134
const mixin = create(proto.Value_CompilerMixinSchema, value);
134135
result.value = {case: 'compilerMixin', value: mixin};
136+
} else if (value instanceof SassModule) {
137+
if (value.compileContext !== this.functions.compileContext) {
138+
throw utils.compilerError(
139+
`Value ${value} does not belong to this compilation`,
140+
);
141+
}
142+
const module = create(proto.Value_CompilerModuleSchema, value);
143+
result.value = {case: 'compilerModule', value: module};
135144
} else if (value instanceof SassCalculation) {
136145
result.value = {
137146
case: 'calculation',
@@ -403,6 +412,12 @@ export class Protofier {
403412
this.functions.compileContext,
404413
);
405414

415+
case 'compilerModule':
416+
return new SassModule(
417+
value.value.value.id,
418+
this.functions.compileContext,
419+
);
420+
406421
case 'calculation':
407422
return this.deprotofyCalculation(value.value.value);
408423

lib/src/value/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {SassString} from './string';
1313
import {valueError} from '../utils';
1414
import {SassCalculation} from './calculations';
1515
import {SassMixin} from './mixin';
16+
import {SassModule} from './module';
1617

1718
/**
1819
* A SassScript value.
@@ -151,6 +152,17 @@ export abstract class Value implements ValueObject {
151152
throw valueError(`${this} is not a mixin reference`, name);
152153
}
153154

155+
/**
156+
* Casts `this` to `SassModule`; throws if `this` isn't a module
157+
* reference.
158+
*
159+
* If `this` came from a function argument, `name` is the argument name
160+
* (without the `$`) and is used for error reporting.
161+
*/
162+
assertModule(name?: string): SassModule {
163+
throw valueError(`${this} is not a module reference`, name);
164+
}
165+
154166
/**
155167
* Casts `this` to `SassMap`; throws if `this` isn't a map.
156168
*

lib/src/value/module.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2026 Google LLC. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
import {hash} from 'immutable';
6+
7+
import {Value} from './index';
8+
9+
/** A first-class SassScript module. */
10+
export class SassModule extends Value {
11+
/**
12+
* This is the unique ID that the compiler uses to determine which module it
13+
* refers to.
14+
*
15+
* This is marked as public so that the protofier can access it, but it's not
16+
* part of the package's public API and should not be accessed by user code.
17+
* It may be renamed or removed without warning in the future.
18+
*/
19+
readonly id: number;
20+
21+
/**
22+
* This is the unique context that the host uses to determine which
23+
* compilation this module belongs to.
24+
*
25+
* This is marked as public so that the protofier can access it, but it's not
26+
* part of the package's public API and should not be accessed by user code.
27+
* It may be renamed or removed without warning in the future.
28+
*/
29+
readonly compileContext: symbol;
30+
31+
constructor(id: number, compileContext: symbol) {
32+
super();
33+
this.id = id;
34+
this.compileContext = compileContext;
35+
}
36+
37+
equals(other: Value): boolean {
38+
return (
39+
other instanceof SassModule &&
40+
other.compileContext === this.compileContext &&
41+
other.id === this.id
42+
);
43+
}
44+
45+
hashCode(): number {
46+
return hash(this.id);
47+
}
48+
49+
toString(): string {
50+
return `<compiler module ${this.id}>`;
51+
}
52+
53+
assertModule(): SassModule {
54+
return this;
55+
}
56+
}

0 commit comments

Comments
 (0)