@master/css-binding 0.0.0-site.1793659883.g69c9aebcf628

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/artifacts/mastercss.node +0 -0
  2. package/artifacts/mcss +0 -0
  3. package/dist/binding-options.d.ts +14 -0
  4. package/dist/binding-options.js +15 -0
  5. package/dist/binding.d.ts +12 -0
  6. package/dist/binding.js +23 -0
  7. package/dist/browser.d.ts +3 -0
  8. package/dist/browser.js +3 -0
  9. package/dist/compiler-binding-adapter.js +55 -0
  10. package/dist/compiler-binding-browser.d.ts +6 -0
  11. package/dist/compiler-binding-browser.js +24 -0
  12. package/dist/compiler-binding-contract.d.ts +45 -0
  13. package/dist/compiler-binding-node.d.ts +5 -0
  14. package/dist/compiler-binding-node.js +20 -0
  15. package/dist/compiler-binding-wasm.js +58 -0
  16. package/dist/compiler-binding.d.ts +6 -0
  17. package/dist/compiler-binding.js +42 -0
  18. package/dist/compiler.js +52 -0
  19. package/dist/engine-binding-adapter.js +61 -0
  20. package/dist/engine-binding-browser.d.ts +8 -0
  21. package/dist/engine-binding-browser.js +35 -0
  22. package/dist/engine-binding-js.js +81 -0
  23. package/dist/engine-binding-node.d.ts +9 -0
  24. package/dist/engine-binding-node.js +38 -0
  25. package/dist/engine-binding-wasm.js +64 -0
  26. package/dist/engine-binding.d.ts +40 -0
  27. package/dist/engine-binding.js +57 -0
  28. package/dist/engine-contract.d.ts +14 -0
  29. package/dist/engine-js/src/animation.js +154 -0
  30. package/dist/engine-js/src/apply.js +207 -0
  31. package/dist/engine-js/src/class-syntax.js +333 -0
  32. package/dist/engine-js/src/condition.js +440 -0
  33. package/dist/engine-js/src/css-syntax.js +247 -0
  34. package/dist/engine-js/src/generate.js +288 -0
  35. package/dist/engine-js/src/mixin.js +328 -0
  36. package/dist/engine-js/src/native-properties.js +5 -0
  37. package/dist/engine-js/src/order.js +97 -0
  38. package/dist/engine-js/src/program-model.js +19 -0
  39. package/dist/engine-js/src/program.js +434 -0
  40. package/dist/engine-js/src/selector.js +195 -0
  41. package/dist/engine-js/src/session.js +540 -0
  42. package/dist/engine-js/src/state.js +62 -0
  43. package/dist/engine-js/src/text.js +51 -0
  44. package/dist/engine-js/src/utility.js +236 -0
  45. package/dist/engine-js/src/value.js +254 -0
  46. package/dist/engine.js +86 -0
  47. package/dist/errors.js +10 -0
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.js +3 -0
  50. package/dist/native-loader.js +134 -0
  51. package/dist/normalize-error.js +63 -0
  52. package/dist/protocol.d.ts +1119 -0
  53. package/dist/protocol.js +14 -0
  54. package/dist/tooling-binding-adapter.js +23 -0
  55. package/dist/tooling-binding-browser.d.ts +5 -0
  56. package/dist/tooling-binding-browser.js +15 -0
  57. package/dist/tooling-binding-contract.d.ts +92 -0
  58. package/dist/tooling-binding-native.js +46 -0
  59. package/dist/tooling-binding-node.d.ts +4 -0
  60. package/dist/tooling-binding-node.js +11 -0
  61. package/dist/tooling-binding-wasm.js +127 -0
  62. package/dist/tooling-binding.d.ts +5 -0
  63. package/dist/tooling-binding.js +21 -0
  64. package/dist/tooling.js +144 -0
  65. package/dist/version.js +3 -0
  66. package/package.json +78 -0
@@ -0,0 +1,540 @@
1
+ import { UTILITY_LAYERS } from "./program-model.js";
2
+ import { compareText, wellFormed } from "./text.js";
3
+ import { cssEscape, decodeProgram } from "./program.js";
4
+ import { compareStoredRules } from "./order.js";
5
+ import { declarationAnimationReferences, generateClassRules } from "./generate.js";
6
+ var EngineError = class extends Error {
7
+ code;
8
+ constructor(code, message) {
9
+ super(message);
10
+ this.code = code;
11
+ }
12
+ };
13
+ function decode(program) {
14
+ const decoded = decodeProgram(program);
15
+ if (!decoded.ok) throw new EngineError(decoded.error.code, decoded.error.message);
16
+ return decoded.program;
17
+ }
18
+ const globalsOf = (emitted = {}) => ({
19
+ variables: new Map(Object.entries(emitted.variables ?? {})),
20
+ keyframes: new Map(Object.entries(emitted.keyframes ?? {}))
21
+ });
22
+ const sameCounts = (left, right) => left.size === right.size && [...left].every(([name, count]) => right.get(name) === count);
23
+ const sameGlobals = (left, right) => sameCounts(left.variables, right.variables) && sameCounts(left.keyframes, right.keyframes);
24
+ /** Counts are `u32`, which adding saturates. */
25
+ const addCount = (count, added) => Math.min(count + added, 4294967295);
26
+ function renderTheme(nodes, active) {
27
+ let text = "";
28
+ for (const node of nodes) if (node.type === "declaration") {
29
+ if (active.has(node.name)) text += `${cssEscape(`--${node.name}`)}:${node.value};`;
30
+ } else {
31
+ const body = renderTheme(node.children, active);
32
+ if (body) text += `${node.prelude}{${body}}`;
33
+ }
34
+ return text.endsWith(";") ? text.slice(0, -1) : text;
35
+ }
36
+ const containersShape = (containers) => containers.map(({ id, prelude }) => ({
37
+ id,
38
+ prelude
39
+ }));
40
+ /** A keyframe definition as the Rust engine serializes it: without its source, and absent options, empty lists and `false` omitted. */
41
+ function keyframeDefinitionShape(definition) {
42
+ return {
43
+ id: definition.id,
44
+ name: definition.name,
45
+ text: definition.text,
46
+ ...definition.containers.length ? { containers: containersShape(definition.containers) } : {},
47
+ ...definition.native ? { native: true } : {},
48
+ ...definition.safelisted ? { safelisted: true } : {},
49
+ ...definition.dependencies.length ? { dependencies: [...definition.dependencies] } : {}
50
+ };
51
+ }
52
+ const samePlacement = (left, right) => left[0] === right[0] && left[1] === right[1] && left[2].length === right[2].length && left[2].every((container, index) => container.id === right[2][index].id && container.prelude === right[2][index].prelude);
53
+ var Session = class {
54
+ program;
55
+ globals;
56
+ /** Per layer, rules in CSS order. */
57
+ layers = UTILITY_LAYERS.map(() => []);
58
+ /** Per layer, each rule by key with the number of classes that reference it. */
59
+ layerRules = UTILITY_LAYERS.map(() => /* @__PURE__ */ new Map());
60
+ classRules = /* @__PURE__ */ new Map();
61
+ /** Connected classes in request order, kept even while they generate no rules. */
62
+ classOrder = /* @__PURE__ */ new Set();
63
+ variableCounts = /* @__PURE__ */ new Map();
64
+ keyframeCounts = /* @__PURE__ */ new Map();
65
+ /** Counts the host emitted, which removing rules never goes below. */
66
+ variableFloors = /* @__PURE__ */ new Map();
67
+ keyframeFloors = /* @__PURE__ */ new Map();
68
+ /** The keyframes rules the host has, in order. */
69
+ keyframeTexts = [];
70
+ themeVariableNames = [];
71
+ themeText;
72
+ themeDirty = false;
73
+ batchDepth = 0;
74
+ disposed = false;
75
+ constructor(program, globals) {
76
+ this.program = program;
77
+ this.globals = globals;
78
+ this.initializeResources();
79
+ this.syncThemeText();
80
+ this.syncKeyframes();
81
+ }
82
+ assertActive() {
83
+ if (this.disposed) throw new EngineError("SESSION_DISPOSED", "Master CSS engine session has been disposed.");
84
+ }
85
+ initializeResources() {
86
+ const { globals, program } = this;
87
+ for (const [name, count] of globals.variables) if (count > 0) this.variableCounts.set(name, count);
88
+ for (const [id, count] of [...globals.keyframes].sort(([left], [right]) => compareText(left, right))) {
89
+ const definition = program.keyframes.find((keyframe) => keyframe.id === id);
90
+ if (!definition || count <= 0) continue;
91
+ this.keyframeCounts.set(id, count);
92
+ this.registerVariables(definition.dependencies);
93
+ }
94
+ for (const definition of program.keyframes) if (definition.safelisted && !this.keyframeCounts.has(definition.id)) {
95
+ this.keyframeCounts.set(definition.id, 1);
96
+ this.registerVariables(definition.dependencies);
97
+ }
98
+ for (const name of program.variableOrder) {
99
+ const variable = program.variables.get(name);
100
+ if (!variable.isStatic) continue;
101
+ this.registerVariable(name);
102
+ if (variable.namespace === "animate") {
103
+ const { names, retainAll } = declarationAnimationReferences(`animation:var(--${name})`, program);
104
+ this.registerKeyframes(names, retainAll);
105
+ }
106
+ }
107
+ this.variableFloors = new Map(this.variableCounts);
108
+ this.keyframeFloors = new Map(this.keyframeCounts);
109
+ }
110
+ /** Counts a variable and, the first time, each dependency it pulls into the theme. */
111
+ registerVariable(name) {
112
+ const visited = /* @__PURE__ */ new Set();
113
+ const stack = [name];
114
+ while (stack.length) {
115
+ const current = stack.pop();
116
+ if (visited.has(current)) continue;
117
+ visited.add(current);
118
+ const variable = this.program.variables.get(current);
119
+ if (!variable) continue;
120
+ for (let index = variable.dependencies.length - 1; index >= 0; index--) stack.push(variable.dependencies[index]);
121
+ const count = (this.variableCounts.get(current) ?? 0) + 1;
122
+ this.variableCounts.set(current, count);
123
+ if (count === 1) {
124
+ this.themeVariableNames.push(current);
125
+ this.themeDirty = true;
126
+ }
127
+ }
128
+ }
129
+ registerVariables(names) {
130
+ for (const name of names) this.registerVariable(name);
131
+ }
132
+ unregisterVariable(name) {
133
+ const visited = /* @__PURE__ */ new Set();
134
+ const stack = [name];
135
+ while (stack.length) {
136
+ const current = stack.pop();
137
+ if (visited.has(current)) continue;
138
+ visited.add(current);
139
+ const variable = this.program.variables.get(current);
140
+ if (!variable) continue;
141
+ for (let index = variable.dependencies.length - 1; index >= 0; index--) stack.push(variable.dependencies[index]);
142
+ const floor = this.variableFloors.get(current) ?? 0;
143
+ const count = this.variableCounts.get(current);
144
+ if (count === void 0 || count <= floor) continue;
145
+ if (floor === 0 && count === 1) {
146
+ this.variableCounts.delete(current);
147
+ this.themeVariableNames = this.themeVariableNames.filter((variableName) => variableName !== current);
148
+ this.themeDirty = true;
149
+ } else this.variableCounts.set(current, count - 1);
150
+ }
151
+ }
152
+ unregisterVariables(names) {
153
+ for (const name of names) this.unregisterVariable(name);
154
+ }
155
+ /** The keyframes a rule references by name, or all of them. */
156
+ referencedKeyframes(names, all) {
157
+ if (!all && !names.length) return [];
158
+ return this.program.keyframes.filter((definition) => all || names.includes(definition.name));
159
+ }
160
+ registerKeyframes(names = [], all = false) {
161
+ for (const definition of this.referencedKeyframes(names, all)) {
162
+ const count = addCount(this.keyframeCounts.get(definition.id) ?? 0, 1);
163
+ this.keyframeCounts.set(definition.id, count);
164
+ if (count === 1) this.registerVariables(definition.dependencies);
165
+ }
166
+ }
167
+ unregisterKeyframes(names = [], all = false) {
168
+ for (const definition of this.referencedKeyframes(names, all)) {
169
+ const count = this.keyframeCounts.get(definition.id);
170
+ if (count === void 0 || count <= (this.keyframeFloors.get(definition.id) ?? 0)) continue;
171
+ if (count === 1) {
172
+ this.keyframeCounts.delete(definition.id);
173
+ this.unregisterVariables(definition.dependencies);
174
+ } else this.keyframeCounts.set(definition.id, count - 1);
175
+ }
176
+ }
177
+ /**
178
+ * Keyframes this session emits: referenced, on demand and not emitted by the host.
179
+ * Native definitions are counted for the tokens their frames read, but their
180
+ * stylesheet delivers them.
181
+ */
182
+ keyframeResources() {
183
+ const resources = [];
184
+ for (const definition of this.program.keyframes) {
185
+ if (definition.native) continue;
186
+ const count = this.keyframeCounts.get(definition.id) ?? 0;
187
+ if (count <= 0 || (this.globals.keyframes.get(definition.id) ?? 0) !== 0) continue;
188
+ const resource = {
189
+ id: definition.id,
190
+ name: definition.name,
191
+ text: definition.text,
192
+ refCount: count,
193
+ dependencies: [...definition.dependencies]
194
+ };
195
+ if (definition.containers.length) resource.containers = containersShape(definition.containers);
196
+ resources.push(resource);
197
+ }
198
+ return resources;
199
+ }
200
+ /** The keyframes rule changes since the last sync. */
201
+ syncKeyframes() {
202
+ const next = this.keyframeResources().map(({ id, text, containers }) => [
203
+ id,
204
+ text,
205
+ containers ?? []
206
+ ]);
207
+ const texts = this.keyframeTexts;
208
+ const mutations = [];
209
+ for (let index = texts.length - 1; index >= 0; index--) {
210
+ if (next.some((placement) => samePlacement(placement, texts[index]))) continue;
211
+ const [[key]] = texts.splice(index, 1);
212
+ mutations.push({
213
+ op: "delete",
214
+ target: "keyframes",
215
+ index,
216
+ key
217
+ });
218
+ }
219
+ for (const [index, placement] of next.entries()) {
220
+ if (texts[index] && samePlacement(texts[index], placement)) continue;
221
+ const [key, text] = placement;
222
+ const previous = texts.findIndex(([id]) => id === key);
223
+ if (previous >= 0) {
224
+ texts.splice(previous, 1);
225
+ mutations.push({
226
+ op: "delete",
227
+ target: "keyframes",
228
+ index: previous,
229
+ key
230
+ });
231
+ }
232
+ texts.splice(index, 0, placement);
233
+ mutations.push({
234
+ op: "insert",
235
+ target: "keyframes",
236
+ index,
237
+ key,
238
+ text
239
+ });
240
+ }
241
+ return mutations;
242
+ }
243
+ /** The emitted keyframes, each wrapped in the containers it was declared in. */
244
+ keyframesText() {
245
+ let text = "";
246
+ let path = [];
247
+ for (const frame of this.keyframeResources()) {
248
+ const containers = frame.containers ?? [];
249
+ let common = 0;
250
+ while (common < path.length && common < containers.length && path[common].id === containers[common].id) common++;
251
+ text += "}".repeat(path.length - common);
252
+ for (const container of containers.slice(common)) text += `${container.prelude}{`;
253
+ text += frame.text;
254
+ path = containers;
255
+ }
256
+ return text + "}".repeat(path.length);
257
+ }
258
+ syncThemeText() {
259
+ if (!this.themeDirty) return;
260
+ this.themeText = renderTheme(this.program.theme, new Set(this.themeVariableNames)) || void 0;
261
+ this.themeDirty = false;
262
+ }
263
+ /**
264
+ * Runs an operation and, outermost, prepends the theme rule change and appends the
265
+ * keyframes rule changes it caused.
266
+ */
267
+ batch(operation) {
268
+ this.assertActive();
269
+ const mutations = [];
270
+ this.batchDepth++;
271
+ try {
272
+ operation(mutations);
273
+ } catch (error) {
274
+ if (!--this.batchDepth) {
275
+ this.syncThemeText();
276
+ this.syncKeyframes();
277
+ }
278
+ throw error;
279
+ }
280
+ if (--this.batchDepth) return {
281
+ version: 5,
282
+ mutations
283
+ };
284
+ if (this.themeDirty) {
285
+ const previous = this.themeText;
286
+ this.syncThemeText();
287
+ if (previous !== this.themeText) {
288
+ const theme = [];
289
+ if (previous !== void 0) theme.push({
290
+ op: "delete",
291
+ target: "theme",
292
+ index: 0,
293
+ key: "theme:root"
294
+ });
295
+ if (this.themeText !== void 0) theme.push({
296
+ op: "insert",
297
+ target: "theme",
298
+ index: 0,
299
+ key: "theme:root",
300
+ text: this.themeText
301
+ });
302
+ mutations.unshift(...theme);
303
+ }
304
+ }
305
+ mutations.push(...this.syncKeyframes());
306
+ return {
307
+ version: 5,
308
+ mutations
309
+ };
310
+ }
311
+ /**
312
+ * Where a rule belongs in its layer. Rules with distinct keys never compare equal,
313
+ * so this is also the index of a stored rule.
314
+ */
315
+ position(layer, rule) {
316
+ const rules = this.layers[layer];
317
+ let low = 0;
318
+ let high = rules.length;
319
+ while (low < high) {
320
+ const middle = low + high >> 1;
321
+ if (compareStoredRules(rules[middle], rule) < 0) low = middle + 1;
322
+ else high = middle;
323
+ }
324
+ return low;
325
+ }
326
+ insertClassRules(className, generated, mutations) {
327
+ const references = [];
328
+ for (const rule of generated) {
329
+ const { key } = rule.ir;
330
+ const layer = UTILITY_LAYERS.indexOf(rule.ir.layer);
331
+ references.push([layer, key]);
332
+ const stored = this.layerRules[layer].get(key);
333
+ if (stored) {
334
+ stored.count++;
335
+ continue;
336
+ }
337
+ this.registerVariables(rule.ir.variableNames ?? []);
338
+ this.registerKeyframes(rule.ir.keyframeNames, rule.ir.retainAllKeyframes);
339
+ const index = this.position(layer, rule);
340
+ this.layers[layer].splice(index, 0, rule);
341
+ this.layerRules[layer].set(key, {
342
+ rule,
343
+ count: 1
344
+ });
345
+ mutations.push({
346
+ op: "insert",
347
+ target: rule.ir.layer,
348
+ index,
349
+ key,
350
+ text: rule.ir.text,
351
+ rule: rule.ir
352
+ });
353
+ }
354
+ this.classOrder.add(className);
355
+ this.classRules.set(className, references);
356
+ }
357
+ ensureClassRules(classNames) {
358
+ return this.batch((mutations) => {
359
+ for (const name of classNames) {
360
+ const className = wellFormed(name);
361
+ if (!className || this.classRules.has(className)) continue;
362
+ this.insertClassRules(className, generateClassRules(className, this.program), mutations);
363
+ }
364
+ });
365
+ }
366
+ deleteClassRules(classNames) {
367
+ return this.batch((mutations) => {
368
+ for (const name of classNames) {
369
+ const className = wellFormed(name);
370
+ const references = this.classRules.get(className);
371
+ if (!references) continue;
372
+ this.classRules.delete(className);
373
+ for (let reference = references.length - 1; reference >= 0; reference--) {
374
+ const [layer, key] = references[reference];
375
+ const stored = this.layerRules[layer].get(key);
376
+ if (!stored) continue;
377
+ if (stored.count > 1) {
378
+ stored.count--;
379
+ continue;
380
+ }
381
+ this.layerRules[layer].delete(key);
382
+ const { rule } = stored;
383
+ const rules = this.layers[layer];
384
+ let index = this.position(layer, rule);
385
+ if (rules[index] !== rule) index = rules.indexOf(rule);
386
+ rules.splice(index, 1);
387
+ mutations.push({
388
+ op: "delete",
389
+ target: UTILITY_LAYERS[layer],
390
+ index,
391
+ key
392
+ });
393
+ this.unregisterVariables(rule.ir.variableNames ?? []);
394
+ this.unregisterKeyframes(rule.ir.keyframeNames, rule.ir.retainAllKeyframes);
395
+ }
396
+ this.classOrder.delete(className);
397
+ }
398
+ });
399
+ }
400
+ /** Re-executes the connected classes against the program and `globals`. */
401
+ rebuild(globals) {
402
+ return this.batch((mutations) => {
403
+ const connected = [...this.classOrder];
404
+ for (let layer = this.layers.length - 1; layer >= 0; layer--) {
405
+ const rules = this.layers[layer];
406
+ for (let index = rules.length - 1; index >= 0; index--) mutations.push({
407
+ op: "delete",
408
+ target: UTILITY_LAYERS[layer],
409
+ index,
410
+ key: rules[index].ir.key
411
+ });
412
+ rules.length = 0;
413
+ this.layerRules[layer].clear();
414
+ }
415
+ this.themeDirty = true;
416
+ this.variableCounts.clear();
417
+ this.keyframeCounts.clear();
418
+ this.themeVariableNames = [];
419
+ this.globals = globals;
420
+ this.classRules.clear();
421
+ this.classOrder.clear();
422
+ this.initializeResources();
423
+ mutations.push(...this.ensureClassRules(connected).mutations);
424
+ });
425
+ }
426
+ /** Adds resource counts the host emitted outside this session to the ones it reported before. */
427
+ registerEmittedGlobals(emittedGlobals) {
428
+ this.assertActive();
429
+ const added = globalsOf(emittedGlobals);
430
+ const merged = {
431
+ variables: new Map(this.globals.variables),
432
+ keyframes: new Map(this.globals.keyframes)
433
+ };
434
+ let changed = false;
435
+ for (const [name, count] of added.variables) {
436
+ if (!count) continue;
437
+ const current = merged.variables.get(name) ?? 0;
438
+ const next = addCount(current, count);
439
+ if (next === current) continue;
440
+ merged.variables.set(name, next);
441
+ changed = true;
442
+ }
443
+ for (const [id, count] of added.keyframes) {
444
+ if (count <= 0) continue;
445
+ merged.keyframes.set(id, addCount(merged.keyframes.get(id) ?? 0, count));
446
+ changed = true;
447
+ }
448
+ return changed ? this.rebuild(merged) : {
449
+ version: 5,
450
+ mutations: []
451
+ };
452
+ }
453
+ /** Replaces the host's resource counts with a complete snapshot, as HMR reports it. */
454
+ replaceEmittedGlobals(emittedGlobals) {
455
+ this.assertActive();
456
+ const globals = globalsOf(emittedGlobals);
457
+ return sameGlobals(globals, this.globals) ? {
458
+ version: 5,
459
+ mutations: []
460
+ } : this.rebuild(globals);
461
+ }
462
+ /** Executes another program, with new emitted globals when given. */
463
+ refresh(program, emittedGlobals) {
464
+ this.assertActive();
465
+ this.program = decode(program);
466
+ return this.rebuild(emittedGlobals === void 0 ? this.globals : globalsOf(emittedGlobals));
467
+ }
468
+ keyframeDefinitions() {
469
+ this.assertActive();
470
+ return this.program.keyframes.map(keyframeDefinitionShape);
471
+ }
472
+ resources() {
473
+ const variables = [];
474
+ for (const name of this.themeVariableNames) {
475
+ const variable = this.program.variables.get(name);
476
+ if (!variable) continue;
477
+ const resource = {
478
+ name,
479
+ refCount: this.variableCounts.get(name) ?? 0
480
+ };
481
+ if (variable.dependencies.length) resource.dependencies = [...variable.dependencies];
482
+ variables.push(resource);
483
+ }
484
+ const keyframes = this.keyframeResources();
485
+ return this.themeText === void 0 ? {
486
+ variables,
487
+ keyframes
488
+ } : {
489
+ themeText: this.themeText,
490
+ variables,
491
+ keyframes
492
+ };
493
+ }
494
+ executionState(classNames) {
495
+ this.assertActive();
496
+ return {
497
+ classes: classNames.map((name) => {
498
+ const className = wellFormed(name);
499
+ return {
500
+ className,
501
+ references: (this.classRules.get(className) ?? []).map(([layer, key]) => ({
502
+ layer: UTILITY_LAYERS[layer],
503
+ key
504
+ }))
505
+ };
506
+ }),
507
+ resources: this.resources()
508
+ };
509
+ }
510
+ snapshot() {
511
+ this.assertActive();
512
+ let text = this.themeText === void 0 ? "" : `@layer theme{${this.themeText}}`;
513
+ for (const [index, rules] of this.layers.entries()) if (rules.length) text += `@layer ${UTILITY_LAYERS[index]}{${rules.map((rule) => rule.ir.text).join("")}}`;
514
+ return {
515
+ version: 5,
516
+ rules: this.layers.flatMap((rules) => rules.map((rule) => rule.ir)),
517
+ resources: this.resources(),
518
+ text: text + this.keyframesText()
519
+ };
520
+ }
521
+ dispose() {
522
+ for (const rules of this.layers) rules.length = 0;
523
+ for (const rules of this.layerRules) rules.clear();
524
+ this.classRules.clear();
525
+ this.classOrder.clear();
526
+ this.variableCounts.clear();
527
+ this.keyframeCounts.clear();
528
+ this.variableFloors.clear();
529
+ this.keyframeFloors.clear();
530
+ this.keyframeTexts = [];
531
+ this.themeVariableNames = [];
532
+ this.themeText = void 0;
533
+ this.themeDirty = false;
534
+ this.disposed = true;
535
+ }
536
+ };
537
+ function createEngineSession(program, emittedGlobals) {
538
+ return new Session(decode(program), globalsOf(emittedGlobals));
539
+ }
540
+ export { EngineError, createEngineSession };
@@ -0,0 +1,62 @@
1
+ import { customMediaBranches } from "./program.js";
2
+ import { splitStateToken } from "./class-syntax.js";
3
+ import { parseCustomMediaQuery, parseNativeQuery, renderConditionToken, resolveLayerCondition } from "./condition.js";
4
+ import { selectorTokenToTemplate, validSelectorStructure } from "./selector.js";
5
+ // ../engine-js/src/state.ts
6
+ /** The branches a state token selects; none when any part of it is invalid or unknown. */
7
+ function resolveStateBranches(stateToken, inheritedImportant, program) {
8
+ let important = inheritedImportant;
9
+ if (stateToken[0] === "!") {
10
+ important = true;
11
+ stateToken = stateToken.slice(1);
12
+ }
13
+ const [selector, conditions] = splitStateToken(stateToken);
14
+ let branches = [{
15
+ key: "",
16
+ conditionWrappers: [],
17
+ important
18
+ }];
19
+ if (selector) {
20
+ const template = selectorTokenToTemplate(selector);
21
+ if (!validSelectorStructure(template)) return [];
22
+ branches[0].key = selector;
23
+ branches[0].selectorTemplate = template;
24
+ }
25
+ for (const condition of conditions) {
26
+ let paths = program.customMediaPaths.get(`--${condition}`);
27
+ if (!paths) {
28
+ const query = parseNativeQuery(condition);
29
+ if (query?.kind === "media" && query.prelude.includes("--")) {
30
+ const media = parseCustomMediaQuery(query.prelude, (name) => program.customMedia.get(name));
31
+ paths = media && customMediaBranches(media);
32
+ if (!paths) return [];
33
+ }
34
+ }
35
+ if (paths) {
36
+ const branchPaths = paths;
37
+ branches = branches.flatMap((branch) => branchPaths.map((path, index) => ({
38
+ ...branch,
39
+ key: `${branch.key}@${condition}#${index}`,
40
+ conditionWrappers: [...branch.conditionWrappers, ...path.map((query) => ["media", `@media ${query}`])]
41
+ })));
42
+ continue;
43
+ }
44
+ const layer = resolveLayerCondition(condition);
45
+ if (layer) {
46
+ branches = branches.filter((branch) => !branch.layer || branch.layer === layer);
47
+ for (const branch of branches) {
48
+ branch.key += `@${condition}`;
49
+ branch.layer = layer;
50
+ }
51
+ continue;
52
+ }
53
+ const wrapper = renderConditionToken(condition, program);
54
+ if (!wrapper) return [];
55
+ for (const branch of branches) {
56
+ branch.key += `@${condition}`;
57
+ branch.conditionWrappers.push(wrapper);
58
+ }
59
+ }
60
+ return branches;
61
+ }
62
+ export { resolveStateBranches };
@@ -0,0 +1,51 @@
1
+ // ../engine-js/src/text.ts
2
+ const isAsciiDigit = (unit) => unit >= 48 && unit <= 57;
3
+ /** Rust `u8::is_ascii_whitespace`, which is also CSS whitespace. */
4
+ const isAsciiWhitespace = (unit) => unit === 32 || unit === 9 || unit === 10 || unit === 12 || unit === 13;
5
+ /** Rust `char::is_whitespace` (Unicode White_Space), which `trim` uses; JS also trims U+FEFF but not U+0085. */
6
+ function isWhitespace(unit) {
7
+ if (unit < 128) return unit === 32 || unit >= 9 && unit <= 13;
8
+ return unit === 133 || unit === 160 || unit === 5760 || unit >= 8192 && unit <= 8202 || unit === 8232 || unit === 8233 || unit === 8239 || unit === 8287 || unit === 12288;
9
+ }
10
+ function trimEnd(value) {
11
+ let end = value.length;
12
+ while (end > 0 && isWhitespace(value.charCodeAt(end - 1))) end--;
13
+ return value.slice(0, end);
14
+ }
15
+ function trim(value) {
16
+ let start = 0;
17
+ while (start < value.length && isWhitespace(value.charCodeAt(start))) start++;
18
+ return trimEnd(value.slice(start));
19
+ }
20
+ const asciiLowercase = (value) => value.replace(/[A-Z]+/g, (letters) => letters.toLowerCase());
21
+ /** Rust `eq_ignore_ascii_case` against a lowercase ASCII `expected`. */
22
+ const isAsciiCase = (value, expected) => value.length === expected.length && asciiLowercase(value) === expected;
23
+ const codePointRank = (unit) => unit >= 55296 ? unit <= 57343 ? unit + 8192 : unit - 2048 : unit;
24
+ /** The Rust `str` (code point) order of two strings. */
25
+ function compareText(left, right) {
26
+ const length = Math.min(left.length, right.length);
27
+ for (let index = 0; index < length; index++) {
28
+ const unit = left.charCodeAt(index);
29
+ const other = right.charCodeAt(index);
30
+ if (unit !== other) return codePointRank(unit) < codePointRank(other) ? -1 : 1;
31
+ }
32
+ return left.length === right.length ? 0 : left.length < right.length ? -1 : 1;
33
+ }
34
+ /** Replaces lone surrogates with U+FFFD, as the UTF-8 boundary of the Rust engine does. */
35
+ function wellFormed(value) {
36
+ if (!/[\ud800-\udfff]/.test(value)) return value;
37
+ let result = "";
38
+ for (let index = 0; index < value.length; index++) {
39
+ const unit = value.charCodeAt(index);
40
+ if (unit >= 55296 && unit <= 56319 && index + 1 < value.length) {
41
+ const next = value.charCodeAt(index + 1);
42
+ if (next >= 56320 && next <= 57343) {
43
+ result += value[index] + value[++index];
44
+ continue;
45
+ }
46
+ }
47
+ result += unit >= 55296 && unit <= 57343 ? "�" : value[index];
48
+ }
49
+ return result;
50
+ }
51
+ export { asciiLowercase, compareText, isAsciiCase, isAsciiDigit, isAsciiWhitespace, isWhitespace, trim, trimEnd, wellFormed };