Skip to content

Commit c708151

Browse files
committed
Fix passing variables across compilations
1 parent 1ec3fbd commit c708151

File tree

5 files changed

+83
-19
lines changed

5 files changed

+83
-19
lines changed

Diff for: lib/src/function-registry.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {Value} from './value';
1818
* execute them.
1919
*/
2020
export class FunctionRegistry<sync extends 'sync' | 'async'> {
21+
public readonly environment = Symbol();
2122
private readonly functionsByName = new Map<string, CustomFunction<sync>>();
2223
private readonly functionsById = new Map<number, CustomFunction<sync>>();
2324
private readonly idsByFunction = new Map<CustomFunction<sync>, number>();

Diff for: lib/src/protofier.ts

+33-11
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class Protofier {
4444
get accessedArgumentLists(): number[] {
4545
return this.argumentLists
4646
.filter(list => list.keywordsAccessed)
47-
.map(list => list.id);
47+
.map(list => list.id as number);
4848
}
4949

5050
constructor(
@@ -85,15 +85,23 @@ export class Protofier {
8585
});
8686
result.value = {case: 'list', value: list};
8787
} else if (value instanceof SassArgumentList) {
88-
const list = create(proto.Value_ArgumentListSchema, {
89-
id: value.id,
90-
separator: this.protofySeparator(value.separator),
91-
contents: value.asList.map(element => this.protofy(element)).toArray(),
92-
});
93-
for (const [key, mapValue] of value.keywordsInternal) {
94-
list.keywords[key] = this.protofy(mapValue);
88+
if (value.environment === this.functions.environment) {
89+
const list = create(proto.Value_ArgumentListSchema, {
90+
id: value.id,
91+
});
92+
result.value = {case: 'argumentList', value: list};
93+
} else {
94+
const list = create(proto.Value_ArgumentListSchema, {
95+
separator: this.protofySeparator(value.separator),
96+
contents: value.asList
97+
.map(element => this.protofy(element))
98+
.toArray(),
99+
});
100+
for (const [key, mapValue] of value.keywordsInternal) {
101+
list.keywords[key] = this.protofy(mapValue);
102+
}
103+
result.value = {case: 'argumentList', value: list};
95104
}
96-
result.value = {case: 'argumentList', value: list};
97105
} else if (value instanceof SassMap) {
98106
const map = create(proto.Value_MapSchema, {
99107
entries: value.contents.toArray().map(([key, value]) => ({
@@ -104,6 +112,11 @@ export class Protofier {
104112
result.value = {case: 'map', value: map};
105113
} else if (value instanceof SassFunction) {
106114
if (value.id !== undefined) {
115+
if (value.environment !== this.functions.environment) {
116+
throw utils.compilerError(
117+
`Value ${value} does not belong to this compilation`,
118+
);
119+
}
107120
const fn = create(proto.Value_CompilerFunctionSchema, value);
108121
result.value = {case: 'compilerFunction', value: fn};
109122
} else {
@@ -114,6 +127,11 @@ export class Protofier {
114127
result.value = {case: 'hostFunction', value: fn};
115128
}
116129
} else if (value instanceof SassMixin) {
130+
if (value.environment !== this.functions.environment) {
131+
throw utils.compilerError(
132+
`Value ${value} does not belong to this compilation`,
133+
);
134+
}
117135
const mixin = create(proto.Value_CompilerMixinSchema, value);
118136
result.value = {case: 'compilerMixin', value: mixin};
119137
} else if (value instanceof SassCalculation) {
@@ -349,6 +367,7 @@ export class Protofier {
349367
),
350368
separator,
351369
list.id,
370+
this.functions.environment,
352371
);
353372
this.argumentLists.push(result);
354373
return result;
@@ -369,15 +388,18 @@ export class Protofier {
369388
);
370389

371390
case 'compilerFunction':
372-
return new SassFunction(value.value.value.id);
391+
return new SassFunction(
392+
value.value.value.id,
393+
this.functions.environment,
394+
);
373395

374396
case 'hostFunction':
375397
throw utils.compilerError(
376398
'The compiler may not send Value.host_function.',
377399
);
378400

379401
case 'compilerMixin':
380-
return new SassMixin(value.value.value.id);
402+
return new SassMixin(value.value.value.id, this.functions.environment);
381403

382404
case 'calculation':
383405
return this.deprotofyCalculation(value.value.value);

Diff for: lib/src/value/argument-list.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,18 @@ export class SassArgumentList extends SassList {
1919
* part of the package's public API and should not be accessed by user code.
2020
* It may be renamed or removed without warning in the future.
2121
*/
22-
readonly id: number;
22+
readonly id: number | undefined;
23+
24+
/**
25+
* If this argument list is constructed in the compiler, this is the unique
26+
* context that the host uses to determine which compilation this argument
27+
* list belongs to.
28+
*
29+
* This is marked as public so that the protofier can access it, but it's not
30+
* part of the package's public API and should not be accessed by user code.
31+
* It may be renamed or removed without warning in the future.
32+
*/
33+
readonly environment: object | undefined;
2334

2435
/**
2536
* The argument list's keywords. This isn't exposed directly so that we can
@@ -54,11 +65,13 @@ export class SassArgumentList extends SassList {
5465
keywords: Record<string, Value> | OrderedMap<string, Value>,
5566
separator?: ListSeparator,
5667
id?: number,
68+
environment?: object,
5769
) {
5870
super(contents, {separator});
5971
this.keywordsInternal = isOrderedMap(keywords)
6072
? keywords
6173
: OrderedMap(keywords);
62-
this.id = id ?? 0;
74+
this.id = id;
75+
this.environment = environment;
6376
}
6477
}

Diff for: lib/src/value/function.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ export class SassFunction extends Value {
1919
*/
2020
readonly id: number | undefined;
2121

22+
/**
23+
* If this function is defined in the compiler, this is the unique context
24+
* that the host uses to determine which compilation this function belongs to.
25+
*
26+
* This is marked as public so that the protofier can access it, but it's not
27+
* part of the package's public API and should not be accessed by user code.
28+
* It may be renamed or removed without warning in the future.
29+
*/
30+
readonly environment: object | undefined;
31+
2232
/**
2333
* If this function is defined in the host, this is the signature that
2434
* describes how to pass arguments to it.
@@ -39,26 +49,29 @@ export class SassFunction extends Value {
3949
*/
4050
readonly callback: CustomFunction<'sync'> | undefined;
4151

42-
constructor(id: number);
52+
constructor(id: number, environment: object);
4353
constructor(signature: string, callback: CustomFunction<'sync'>);
4454
constructor(
4555
idOrSignature: number | string,
46-
callback?: CustomFunction<'sync'>,
56+
callbackOrEnvironment: CustomFunction<'sync'> | object,
4757
) {
4858
super();
4959

5060
if (typeof idOrSignature === 'number') {
5161
this.id = idOrSignature;
62+
this.environment = callbackOrEnvironment;
5263
} else {
5364
this.signature = idOrSignature;
54-
this.callback = callback!;
65+
this.callback = callbackOrEnvironment as CustomFunction<'sync'>;
5566
}
5667
}
5768

5869
equals(other: Value): boolean {
5970
return this.id === undefined
6071
? other === this
61-
: other instanceof SassFunction && other.id === this.id;
72+
: other instanceof SassFunction &&
73+
other.environment === this.environment &&
74+
other.id === this.id;
6275
}
6376

6477
hashCode(): number {

Diff for: lib/src/value/mixin.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,28 @@ export class SassMixin extends Value {
1818
*/
1919
readonly id: number;
2020

21-
constructor(id: number) {
21+
/**
22+
* This is the unique context that the host uses to determine which
23+
* compilation this mixin 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 environment: object;
30+
31+
constructor(id: number, environment: object) {
2232
super();
2333
this.id = id;
34+
this.environment = environment;
2435
}
2536

2637
equals(other: Value): boolean {
27-
return other instanceof SassMixin && other.id === this.id;
38+
return (
39+
other instanceof SassMixin &&
40+
other.environment === this.environment &&
41+
other.id === this.id
42+
);
2843
}
2944

3045
hashCode(): number {

0 commit comments

Comments
 (0)