@teacss/engine 0.9.0 → 0.9.2
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.
- package/README.md +49 -5
- package/binding.js +54 -54
- package/contract.d.ts +1 -1
- package/dist/config-view.d.ts +9 -0
- package/dist/config-view.js +38 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +4 -0
- package/dist/generator.d.ts +10 -2
- package/dist/generator.js +85 -20
- package/dist/select.d.ts +1 -1
- package/dist/select.js +16 -4
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -22,19 +22,63 @@ Every package needs Node.js 22.12.0 or later; the wasm package needs `>=22.13.0
|
|
|
22
22
|
|
|
23
23
|
## Engine selection
|
|
24
24
|
|
|
25
|
-
- `TEACSS_ENGINE=auto|rust|ts` overrides
|
|
26
|
-
- Otherwise the integration's `engine` option decides
|
|
27
|
-
- `package.json#engineCompat.defaultMode` sets what the option `"auto"` means.
|
|
28
|
-
- With `"auto"`, a configuration Rust cannot serve falls back to TypeScript with a machine-readable reason; with `"rust"`, the
|
|
25
|
+
- `TEACSS_ENGINE=auto|rust|ts` overrides the `engine` option. An unrecognized value is ignored, and the selection result carries it as `invalidEnv`.
|
|
26
|
+
- Otherwise the integration's `engine` option decides. `selectEngineRequest` with no option returns TypeScript; what an unset `engine` means is the teacss-ts hook's call.
|
|
27
|
+
- `package.json#engineCompat.defaultMode` sets what the option `"auto"` means. It is `"auto"`: `engine: "auto"`, which the first-party integrations pass, tries Rust and falls back to TypeScript when the configuration cannot run there. Releases up to 0.9.1 shipped `"opt-in"`, under which the option `"auto"` stayed on TypeScript and only `TEACSS_ENGINE=rust|auto` or `engine: "rust"` tried Rust.
|
|
28
|
+
- With `"auto"`, a configuration Rust cannot serve falls back to TypeScript with a machine-readable reason (see [Fallback reasons](#fallback-reasons)); with `"rust"`, the teacss-ts hook prints the same fallback as a warning, and throws instead when `TEACSS_ENGINE_STRICT=1` is set.
|
|
29
29
|
|
|
30
30
|
`selectEngineRequest` from `@teacss/engine/select` (which does not load the binding) stays on TypeScript in three cases: `mode: "ts"` (TypeScript chosen explicitly), `resolvedBy: "opt-in"` (the option `"auto"` while `defaultMode` is `"opt-in"`), and `reason: "engine-compat"` (the host `@teacss/core` is outside `engineCompat.core`).
|
|
31
31
|
|
|
32
|
+
## Fallback reasons
|
|
33
|
+
|
|
34
|
+
A fallback prints one line per reason and path per process: `[teacss] engine: falling back to the TypeScript engine (<reason> at <path>)`. In teacss-ts, `TEACSS_ENGINE_STATS=1` prints on exit how many generators ran on each engine and which reasons fell back. `TEACSS_ENGINE_DEBUG=1` makes this package print the translated request or the first failure to stderr. The facade stops at the first item it cannot translate, so fixing one reason can reveal the next.
|
|
35
|
+
|
|
36
|
+
To keep TypeScript for any configuration, set `TEACSS_ENGINE=ts` (it covers every integration), or write `engine: "ts"` in the configuration or in the host's defaults, for example `pluginTeacss(config, { engine: "ts" })`. A fallback is not an error: the TypeScript engine produces the same CSS it always has.
|
|
37
|
+
|
|
38
|
+
`<i>` is the preset's index after nested presets are flattened and ordered by `enforce`.
|
|
39
|
+
|
|
40
|
+
| Reason | Path | What it means and why | To run on Rust |
|
|
41
|
+
| --- | --- | --- | --- |
|
|
42
|
+
| `engine-unavailable` | `@teacss/engine` | Reported by the teacss-ts hook, not by this package: importing the facade failed, usually because no platform package matches the machine or the native binding did not load. | Install the platform package for your machine; see [Troubleshooting](#troubleshooting). `TEACSS_ENGINE=rust` throws with the loader's error instead of falling back. |
|
|
43
|
+
| `engine-compat` | `@teacss/core` | The host `@teacss/core` is outside `engineCompat.core`, so the pair was not tested together. `TEACSS_ENGINE=rust` throws `E_ENGINE_COMPAT` instead. | Align `@teacss/core` and `@teacss/engine`; check the lockfile for a second copy of either. |
|
|
44
|
+
| `unknown-key` | the key | A top-level config key the facade does not know, such as a typo or an option from a newer core. Rust cannot know what it means. | Remove or correct the key. |
|
|
45
|
+
| `rules`, `variants`, `extractors`, `extractorDefault`, `preflights`, `preprocess`, `postprocess`, `extendTheme`, `configResolved`, `autocomplete`, `cli` | the key | The key has a non-empty value. These hold functions or matchers that only JavaScript can run, and Rust does not execute JavaScript. | Remove the key from the configuration the integration loads, or express it statically with `shortcuts`, `theme`, `safelist` or a preset option. |
|
|
46
|
+
| `separators` | `separators` | Separators other than the default `[":", "-"]`; Rust parses only the default. | Remove `separators`. |
|
|
47
|
+
| `mergeSelectors` | `mergeSelectors` | `mergeSelectors: false`; Rust always merges selectors. | Remove it. |
|
|
48
|
+
| `details` | `details` | `details` is set; Rust does not support it. | Remove it. |
|
|
49
|
+
| `sortLayers` | `sortLayers` | A `sortLayers` function. | Remove it and order layers with `layers`. |
|
|
50
|
+
| `content` | `content` or `content.filesystem` | `content` is not an object, or `content.filesystem` is not an array of strings. | Use an array of glob strings. |
|
|
51
|
+
| `content.inline` | `content.inline` | Inline content sources, which only the TypeScript engine reads. | Move the content into files matched by `content.filesystem`. |
|
|
52
|
+
| `envMode` | `envMode` | A value other than `"dev"` or `"build"`. | Use one of the two. |
|
|
53
|
+
| `unmatched` | `unmatched` | A value other than `"warn"`, `"error"` or `"off"`. | Use one of the three. |
|
|
54
|
+
| `outputToCssLayers` | `outputToCssLayers` | Neither a boolean nor an object. | Use `true`, `false` or `{ allLayers }`. |
|
|
55
|
+
| `outputToCssLayers.cssLayerName` | `outputToCssLayers.cssLayerName` | A `cssLayerName` value; Rust does not support it. | Remove it. |
|
|
56
|
+
| `transformers` | `transformers` or `transformers[<n>]` | A transformer other than `@teacss/transformer-compile-class` and `@teacss/directives`, or a `transformers` value that is not an array. Other transformers run JavaScript over the source. | Remove the transformer, or keep TypeScript. |
|
|
57
|
+
| `shortcuts`, `safelist`, `blocklist`, `theme`, `layers` | the key and the item inside it | A value that is not static data: a shortcut whose expansion is not a string, or that has a regular expression or meta; a `safelist` or `blocklist` item that is not a string; a theme leaf that is not a string or number, or the removed `rolePalettes` theme key; a layer order that is not a number. | Replace the item with static data. |
|
|
58
|
+
| `preset-not-instantiated` | `presets[<n>]` | A preset that is a function, a promise or not an object. | Call the factory (`presetStandard()`, not `presetStandard`) and await it before passing it. |
|
|
59
|
+
| `preset-cycle` | `presets[<n>]…` | A preset that contains itself through nested `presets`. | Break the cycle. |
|
|
60
|
+
| `accessor` | the key | A getter or setter on the config, the defaults or a preset. Translation would run it once and the TypeScript engine again. | Use plain data properties. |
|
|
61
|
+
| `standard.unknown-option` | `presets[<i>].options.<key>` | A Standard option other than `modeSelectors`, `containers`, `preflight`, `variablePrefix` and `compileClass`. | Remove the option. |
|
|
62
|
+
| `standard.compileClass.hashFn`, `standard.compileClass.trigger` | `presets[<i>].options.compileClass.…` | A custom hash function or trigger for compiled classes. | Remove it; `classPrefix`, `alwaysHash`, `keepUnknown` and `layer` are supported. |
|
|
63
|
+
| `icons.collections` | `presets[<i>].options.collections.<name>` | An icon collection other than the bundled `carbon`, `crypto`, `flagpack`, `logo` and `lucide`. | Use a bundled collection, or keep TypeScript. |
|
|
64
|
+
| `icons.customizations`, `icons.processor` | `presets[<i>].options.…` | Icon customizations or a processor, which run JavaScript. | Remove them. |
|
|
65
|
+
| `role-palettes-without-entry` | `presets[<i>]` | The `@teacss/config/role-palettes` preset in a configuration that did not come from an entry stylesheet. On Rust the preset needs the entry. | Load the configuration from its entry stylesheet through `@teacss/config`. |
|
|
66
|
+
| `preset.name` | `presets[<i>].name` | A preset without a string `name`. | Give the preset a name. |
|
|
67
|
+
| `preset.rules`, `preset.variants`, `preset.extractors`, `preset.preflights`, `preset.preprocess`, `preset.postprocess`, `preset.extendTheme`, `preset.configResolved`, `preset.transformers`, `preset.autocomplete`, `preset.extractorDefault` | `presets[<i>].<key>` | A preset that is not one of the built-in presets carries a dynamic field, as for the top-level keys above. | Remove the field from the preset, or keep TypeScript. |
|
|
68
|
+
| `preset.content` | `presets[<i>].content` | A preset's `content` holds something other than `pipeline`, such as `filesystem` or `inline`; Rust reads content globs only from the configuration. | Move the globs to the configuration's `content.filesystem`. |
|
|
69
|
+
| `preset.shortcuts`, `preset.safelist`, `preset.blocklist`, `preset.theme`, `preset.layers` | `presets[<i>].<key>…` | A preset field that is not static data, as for the top-level keys above. | Replace the item with static data. |
|
|
70
|
+
| `preset.enforce`, `preset.layer` | `presets[<i>].<key>` | `enforce` other than `"pre"` or `"post"`, or a `layer` that is not a string. | Correct the value. |
|
|
71
|
+
| `declarations-unsaved` | the declaration file | A declaration file whose text came from an unsaved editor buffer. Rust reads declaration files from disk. | Save the file. |
|
|
72
|
+
| `declarations-unavailable` | `content.filesystem` | Finding declaration files under `content.filesystem` failed: the `@teacss/config` source scanner could not be loaded, or it threw. | Install `@teacss/config`. |
|
|
73
|
+
|
|
74
|
+
`content.pipeline` never falls back, in the configuration or in a preset, whatever it holds (RegExp, functions or `false`). It only decides which modules the integration feeds in, so it stays on the facade's `config.content` and is not sent to Rust.
|
|
75
|
+
|
|
32
76
|
## Compatibility
|
|
33
77
|
|
|
34
78
|
| `engineCompat` field | Meaning |
|
|
35
79
|
| --- | --- |
|
|
36
80
|
| `core` | The `@teacss/core` versions this engine accepts, written as `>=A.B.C <X.Y.Z`; prereleases compare by SemVer, so `0.9.0-alpha.1 < 0.9.0` |
|
|
37
|
-
| `defaultMode` | What the option `"auto"` means: `"opt-in"` keeps TypeScript, `"auto"` tries Rust |
|
|
81
|
+
| `defaultMode` | What the option `"auto"` means: `"opt-in"` keeps TypeScript, `"auto"` (the current value) tries Rust |
|
|
38
82
|
| `oracle.teacssTs` / `oracle.commit` | The teacss-ts version and commit this release was compared against byte for byte |
|
|
39
83
|
|
|
40
84
|
| `@teacss/core` | `@teacss/engine` | `engineCompat.core` | Result |
|
package/binding.js
CHANGED
|
@@ -92,8 +92,8 @@ function requireNative() {
|
|
|
92
92
|
try {
|
|
93
93
|
const binding = require('@teacss/engine-android-arm64')
|
|
94
94
|
const bindingPackageVersion = require('@teacss/engine-android-arm64/package.json').version
|
|
95
|
-
if (bindingPackageVersion !== '0.9.
|
|
96
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
95
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
96
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
97
97
|
}
|
|
98
98
|
return binding
|
|
99
99
|
} catch (e) {
|
|
@@ -108,8 +108,8 @@ function requireNative() {
|
|
|
108
108
|
try {
|
|
109
109
|
const binding = require('@teacss/engine-android-arm-eabi')
|
|
110
110
|
const bindingPackageVersion = require('@teacss/engine-android-arm-eabi/package.json').version
|
|
111
|
-
if (bindingPackageVersion !== '0.9.
|
|
112
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
111
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
112
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
113
113
|
}
|
|
114
114
|
return binding
|
|
115
115
|
} catch (e) {
|
|
@@ -129,8 +129,8 @@ function requireNative() {
|
|
|
129
129
|
try {
|
|
130
130
|
const binding = require('@teacss/engine-win32-x64-gnu')
|
|
131
131
|
const bindingPackageVersion = require('@teacss/engine-win32-x64-gnu/package.json').version
|
|
132
|
-
if (bindingPackageVersion !== '0.9.
|
|
133
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
132
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
133
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
134
134
|
}
|
|
135
135
|
return binding
|
|
136
136
|
} catch (e) {
|
|
@@ -145,8 +145,8 @@ function requireNative() {
|
|
|
145
145
|
try {
|
|
146
146
|
const binding = require('@teacss/engine-win32-x64-msvc')
|
|
147
147
|
const bindingPackageVersion = require('@teacss/engine-win32-x64-msvc/package.json').version
|
|
148
|
-
if (bindingPackageVersion !== '0.9.
|
|
149
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
148
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
149
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
150
150
|
}
|
|
151
151
|
return binding
|
|
152
152
|
} catch (e) {
|
|
@@ -162,8 +162,8 @@ function requireNative() {
|
|
|
162
162
|
try {
|
|
163
163
|
const binding = require('@teacss/engine-win32-ia32-msvc')
|
|
164
164
|
const bindingPackageVersion = require('@teacss/engine-win32-ia32-msvc/package.json').version
|
|
165
|
-
if (bindingPackageVersion !== '0.9.
|
|
166
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
165
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
166
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
167
167
|
}
|
|
168
168
|
return binding
|
|
169
169
|
} catch (e) {
|
|
@@ -178,8 +178,8 @@ function requireNative() {
|
|
|
178
178
|
try {
|
|
179
179
|
const binding = require('@teacss/engine-win32-arm64-msvc')
|
|
180
180
|
const bindingPackageVersion = require('@teacss/engine-win32-arm64-msvc/package.json').version
|
|
181
|
-
if (bindingPackageVersion !== '0.9.
|
|
182
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
181
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
182
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
183
183
|
}
|
|
184
184
|
return binding
|
|
185
185
|
} catch (e) {
|
|
@@ -197,8 +197,8 @@ function requireNative() {
|
|
|
197
197
|
try {
|
|
198
198
|
const binding = require('@teacss/engine-darwin-universal')
|
|
199
199
|
const bindingPackageVersion = require('@teacss/engine-darwin-universal/package.json').version
|
|
200
|
-
if (bindingPackageVersion !== '0.9.
|
|
201
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
200
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
201
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
202
202
|
}
|
|
203
203
|
return binding
|
|
204
204
|
} catch (e) {
|
|
@@ -213,8 +213,8 @@ function requireNative() {
|
|
|
213
213
|
try {
|
|
214
214
|
const binding = require('@teacss/engine-darwin-x64')
|
|
215
215
|
const bindingPackageVersion = require('@teacss/engine-darwin-x64/package.json').version
|
|
216
|
-
if (bindingPackageVersion !== '0.9.
|
|
217
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
216
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
217
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
218
218
|
}
|
|
219
219
|
return binding
|
|
220
220
|
} catch (e) {
|
|
@@ -229,8 +229,8 @@ function requireNative() {
|
|
|
229
229
|
try {
|
|
230
230
|
const binding = require('@teacss/engine-darwin-arm64')
|
|
231
231
|
const bindingPackageVersion = require('@teacss/engine-darwin-arm64/package.json').version
|
|
232
|
-
if (bindingPackageVersion !== '0.9.
|
|
233
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
232
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
233
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
234
234
|
}
|
|
235
235
|
return binding
|
|
236
236
|
} catch (e) {
|
|
@@ -249,8 +249,8 @@ function requireNative() {
|
|
|
249
249
|
try {
|
|
250
250
|
const binding = require('@teacss/engine-freebsd-x64')
|
|
251
251
|
const bindingPackageVersion = require('@teacss/engine-freebsd-x64/package.json').version
|
|
252
|
-
if (bindingPackageVersion !== '0.9.
|
|
253
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
252
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
253
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
254
254
|
}
|
|
255
255
|
return binding
|
|
256
256
|
} catch (e) {
|
|
@@ -265,8 +265,8 @@ function requireNative() {
|
|
|
265
265
|
try {
|
|
266
266
|
const binding = require('@teacss/engine-freebsd-arm64')
|
|
267
267
|
const bindingPackageVersion = require('@teacss/engine-freebsd-arm64/package.json').version
|
|
268
|
-
if (bindingPackageVersion !== '0.9.
|
|
269
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
268
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
269
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
270
270
|
}
|
|
271
271
|
return binding
|
|
272
272
|
} catch (e) {
|
|
@@ -286,8 +286,8 @@ function requireNative() {
|
|
|
286
286
|
try {
|
|
287
287
|
const binding = require('@teacss/engine-linux-x64-musl')
|
|
288
288
|
const bindingPackageVersion = require('@teacss/engine-linux-x64-musl/package.json').version
|
|
289
|
-
if (bindingPackageVersion !== '0.9.
|
|
290
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
289
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
290
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
291
291
|
}
|
|
292
292
|
return binding
|
|
293
293
|
} catch (e) {
|
|
@@ -302,8 +302,8 @@ function requireNative() {
|
|
|
302
302
|
try {
|
|
303
303
|
const binding = require('@teacss/engine-linux-x64-gnu')
|
|
304
304
|
const bindingPackageVersion = require('@teacss/engine-linux-x64-gnu/package.json').version
|
|
305
|
-
if (bindingPackageVersion !== '0.9.
|
|
306
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
305
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
306
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
307
307
|
}
|
|
308
308
|
return binding
|
|
309
309
|
} catch (e) {
|
|
@@ -320,8 +320,8 @@ function requireNative() {
|
|
|
320
320
|
try {
|
|
321
321
|
const binding = require('@teacss/engine-linux-arm64-musl')
|
|
322
322
|
const bindingPackageVersion = require('@teacss/engine-linux-arm64-musl/package.json').version
|
|
323
|
-
if (bindingPackageVersion !== '0.9.
|
|
324
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
323
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
324
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
325
325
|
}
|
|
326
326
|
return binding
|
|
327
327
|
} catch (e) {
|
|
@@ -336,8 +336,8 @@ function requireNative() {
|
|
|
336
336
|
try {
|
|
337
337
|
const binding = require('@teacss/engine-linux-arm64-gnu')
|
|
338
338
|
const bindingPackageVersion = require('@teacss/engine-linux-arm64-gnu/package.json').version
|
|
339
|
-
if (bindingPackageVersion !== '0.9.
|
|
340
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
339
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
340
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
341
341
|
}
|
|
342
342
|
return binding
|
|
343
343
|
} catch (e) {
|
|
@@ -354,8 +354,8 @@ function requireNative() {
|
|
|
354
354
|
try {
|
|
355
355
|
const binding = require('@teacss/engine-linux-arm-musleabihf')
|
|
356
356
|
const bindingPackageVersion = require('@teacss/engine-linux-arm-musleabihf/package.json').version
|
|
357
|
-
if (bindingPackageVersion !== '0.9.
|
|
358
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
357
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
358
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
359
359
|
}
|
|
360
360
|
return binding
|
|
361
361
|
} catch (e) {
|
|
@@ -370,8 +370,8 @@ function requireNative() {
|
|
|
370
370
|
try {
|
|
371
371
|
const binding = require('@teacss/engine-linux-arm-gnueabihf')
|
|
372
372
|
const bindingPackageVersion = require('@teacss/engine-linux-arm-gnueabihf/package.json').version
|
|
373
|
-
if (bindingPackageVersion !== '0.9.
|
|
374
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
373
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
374
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
375
375
|
}
|
|
376
376
|
return binding
|
|
377
377
|
} catch (e) {
|
|
@@ -388,8 +388,8 @@ function requireNative() {
|
|
|
388
388
|
try {
|
|
389
389
|
const binding = require('@teacss/engine-linux-loong64-musl')
|
|
390
390
|
const bindingPackageVersion = require('@teacss/engine-linux-loong64-musl/package.json').version
|
|
391
|
-
if (bindingPackageVersion !== '0.9.
|
|
392
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
391
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
392
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
393
393
|
}
|
|
394
394
|
return binding
|
|
395
395
|
} catch (e) {
|
|
@@ -404,8 +404,8 @@ function requireNative() {
|
|
|
404
404
|
try {
|
|
405
405
|
const binding = require('@teacss/engine-linux-loong64-gnu')
|
|
406
406
|
const bindingPackageVersion = require('@teacss/engine-linux-loong64-gnu/package.json').version
|
|
407
|
-
if (bindingPackageVersion !== '0.9.
|
|
408
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
407
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
408
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
409
409
|
}
|
|
410
410
|
return binding
|
|
411
411
|
} catch (e) {
|
|
@@ -422,8 +422,8 @@ function requireNative() {
|
|
|
422
422
|
try {
|
|
423
423
|
const binding = require('@teacss/engine-linux-riscv64-musl')
|
|
424
424
|
const bindingPackageVersion = require('@teacss/engine-linux-riscv64-musl/package.json').version
|
|
425
|
-
if (bindingPackageVersion !== '0.9.
|
|
426
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
425
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
426
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
427
427
|
}
|
|
428
428
|
return binding
|
|
429
429
|
} catch (e) {
|
|
@@ -438,8 +438,8 @@ function requireNative() {
|
|
|
438
438
|
try {
|
|
439
439
|
const binding = require('@teacss/engine-linux-riscv64-gnu')
|
|
440
440
|
const bindingPackageVersion = require('@teacss/engine-linux-riscv64-gnu/package.json').version
|
|
441
|
-
if (bindingPackageVersion !== '0.9.
|
|
442
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
441
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
442
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
443
443
|
}
|
|
444
444
|
return binding
|
|
445
445
|
} catch (e) {
|
|
@@ -455,8 +455,8 @@ function requireNative() {
|
|
|
455
455
|
try {
|
|
456
456
|
const binding = require('@teacss/engine-linux-ppc64-gnu')
|
|
457
457
|
const bindingPackageVersion = require('@teacss/engine-linux-ppc64-gnu/package.json').version
|
|
458
|
-
if (bindingPackageVersion !== '0.9.
|
|
459
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
458
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
459
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
460
460
|
}
|
|
461
461
|
return binding
|
|
462
462
|
} catch (e) {
|
|
@@ -471,8 +471,8 @@ function requireNative() {
|
|
|
471
471
|
try {
|
|
472
472
|
const binding = require('@teacss/engine-linux-s390x-gnu')
|
|
473
473
|
const bindingPackageVersion = require('@teacss/engine-linux-s390x-gnu/package.json').version
|
|
474
|
-
if (bindingPackageVersion !== '0.9.
|
|
475
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
474
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
475
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
476
476
|
}
|
|
477
477
|
return binding
|
|
478
478
|
} catch (e) {
|
|
@@ -491,8 +491,8 @@ function requireNative() {
|
|
|
491
491
|
try {
|
|
492
492
|
const binding = require('@teacss/engine-openharmony-arm64')
|
|
493
493
|
const bindingPackageVersion = require('@teacss/engine-openharmony-arm64/package.json').version
|
|
494
|
-
if (bindingPackageVersion !== '0.9.
|
|
495
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
494
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
495
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
496
496
|
}
|
|
497
497
|
return binding
|
|
498
498
|
} catch (e) {
|
|
@@ -507,8 +507,8 @@ function requireNative() {
|
|
|
507
507
|
try {
|
|
508
508
|
const binding = require('@teacss/engine-openharmony-x64')
|
|
509
509
|
const bindingPackageVersion = require('@teacss/engine-openharmony-x64/package.json').version
|
|
510
|
-
if (bindingPackageVersion !== '0.9.
|
|
511
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
510
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
511
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
512
512
|
}
|
|
513
513
|
return binding
|
|
514
514
|
} catch (e) {
|
|
@@ -523,8 +523,8 @@ function requireNative() {
|
|
|
523
523
|
try {
|
|
524
524
|
const binding = require('@teacss/engine-openharmony-arm')
|
|
525
525
|
const bindingPackageVersion = require('@teacss/engine-openharmony-arm/package.json').version
|
|
526
|
-
if (bindingPackageVersion !== '0.9.
|
|
527
|
-
throw new Error(`Native binding package version mismatch, expected 0.9.
|
|
526
|
+
if (bindingPackageVersion !== '0.9.2' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
527
|
+
throw new Error(`Native binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
528
528
|
}
|
|
529
529
|
return binding
|
|
530
530
|
} catch (e) {
|
|
@@ -664,8 +664,8 @@ if (!nativeBinding || forceWasi) {
|
|
|
664
664
|
if (!candidateFailed) {
|
|
665
665
|
if (process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
|
666
666
|
const bindingPackageVersion = require('@teacss/engine-wasm32-wasi/package.json').version
|
|
667
|
-
if (bindingPackageVersion !== '0.9.
|
|
668
|
-
throw new Error(`WASI binding package version mismatch, expected 0.9.
|
|
667
|
+
if (bindingPackageVersion !== '0.9.2') {
|
|
668
|
+
throw new Error(`WASI binding package version mismatch, expected 0.9.2 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
|
669
669
|
}
|
|
670
670
|
}
|
|
671
671
|
wasiBinding = require('@teacss/engine-wasm32-wasi')
|
package/contract.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Mirror of docs/specs/v02.2-engine-contract.md §3 (spec-revision
|
|
1
|
+
// Mirror of docs/specs/v02.2-engine-contract.md §3 (spec-revision 13). Do not edit without bumping the spec revision.
|
|
2
2
|
export interface InspectEntryRequest {
|
|
3
3
|
/** 项目根(绝对路径)。相对 @source 以声明它的文件所在目录为基准。 */
|
|
4
4
|
root: string;
|
package/dist/config-view.d.ts
CHANGED
|
@@ -23,5 +23,14 @@ export interface ConfigViewArgs {
|
|
|
23
23
|
compileClassShortcuts(): unknown[];
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* The merged `content.pipeline` of the presets and the config, as `mergeContentOptions`
|
|
28
|
+
* (core/config.ts) builds it: `false` anywhere disables it, otherwise includes and excludes
|
|
29
|
+
* concatenate in source order without duplicates. The runtime builds its module filter from it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function mergePipeline(sources: readonly unknown[]): false | {
|
|
32
|
+
include?: Array<string | RegExp>;
|
|
33
|
+
exclude?: Array<string | RegExp>;
|
|
34
|
+
} | undefined;
|
|
26
35
|
export declare function createConfigView({ view, presets, merged, transformers, host, fallback, engine }: ConfigViewArgs): Record<string, unknown>;
|
|
27
36
|
//# sourceMappingURL=config-view.d.ts.map
|
package/dist/config-view.js
CHANGED
|
@@ -38,6 +38,40 @@ const RESOLVED_KEYS = Object.freeze([
|
|
|
38
38
|
"content",
|
|
39
39
|
"transformers",
|
|
40
40
|
]);
|
|
41
|
+
const ownValue = (source, key) => (source !== null && typeof source === "object" && Object.hasOwn(source, key) ? source[key] : undefined);
|
|
42
|
+
const flattenPatterns = (patterns) => [...new Set(patterns.flatMap((pattern) => (Array.isArray(pattern) ? pattern : pattern ? [pattern] : [])))];
|
|
43
|
+
/**
|
|
44
|
+
* The merged `content.pipeline` of the presets and the config, as `mergeContentOptions`
|
|
45
|
+
* (core/config.ts) builds it: `false` anywhere disables it, otherwise includes and excludes
|
|
46
|
+
* concatenate in source order without duplicates. The runtime builds its module filter from it.
|
|
47
|
+
*/
|
|
48
|
+
export function mergePipeline(sources) {
|
|
49
|
+
const includes = [];
|
|
50
|
+
const excludes = [];
|
|
51
|
+
let configured = false;
|
|
52
|
+
for (const content of new Set(sources.map((source) => ownValue(source, "content")).filter((content) => content !== undefined && content !== null))) {
|
|
53
|
+
const pipeline = ownValue(content, "pipeline");
|
|
54
|
+
if (pipeline === false)
|
|
55
|
+
return false;
|
|
56
|
+
if (pipeline === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
configured = true;
|
|
59
|
+
const include = pipeline && ownValue(pipeline, "include");
|
|
60
|
+
const exclude = pipeline && ownValue(pipeline, "exclude");
|
|
61
|
+
if (include)
|
|
62
|
+
includes.push(include);
|
|
63
|
+
if (exclude)
|
|
64
|
+
excludes.push(exclude);
|
|
65
|
+
}
|
|
66
|
+
if (!configured)
|
|
67
|
+
return undefined;
|
|
68
|
+
const merged = {};
|
|
69
|
+
if (includes.length)
|
|
70
|
+
merged.include = flattenPatterns(includes);
|
|
71
|
+
if (excludes.length)
|
|
72
|
+
merged.exclude = flattenPatterns(excludes);
|
|
73
|
+
return merged;
|
|
74
|
+
}
|
|
41
75
|
export function createConfigView({ view, presets, merged, transformers, host, fallback, engine }) {
|
|
42
76
|
const config = {};
|
|
43
77
|
const data = (key, value) => Object.defineProperty(config, key, { value, enumerable: true, configurable: true, writable: true });
|
|
@@ -54,7 +88,10 @@ export function createConfigView({ view, presets, merged, transformers, host, fa
|
|
|
54
88
|
const extractors = host.core ? [host.core.extractorSplit] : [{ name: view.extractors?.[0]?.name ?? "@teacss/core/extractor-split" }];
|
|
55
89
|
const fields = {
|
|
56
90
|
presets: () => data("presets", presets),
|
|
57
|
-
content: () =>
|
|
91
|
+
content: () => {
|
|
92
|
+
const pipeline = mergePipeline([...presets, merged]);
|
|
93
|
+
data("content", pipeline === undefined ? (view.content ?? {}) : { pipeline, ...view.content });
|
|
94
|
+
},
|
|
58
95
|
transformers: () => data("transformers", transformers),
|
|
59
96
|
extractors: () => data("extractors", extractors),
|
|
60
97
|
extractorDefault: () => data("extractorDefault", extractors[0]),
|
package/dist/errors.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare class TeacssEngineError extends Error {
|
|
|
6
6
|
}
|
|
7
7
|
/** v02.9 §2.1: the member needs `@teacss/core`, which is not installed. */
|
|
8
8
|
export declare function tsRequiredError(member: string): TeacssEngineError;
|
|
9
|
+
/** The generator was disposed; the native Engine reports the same code after its own `dispose()`. */
|
|
10
|
+
export declare function disposedError(member: string): TeacssEngineError;
|
|
9
11
|
/** v02.9 §3.3: the member needs the TypeScript engine, which has not been materialized. */
|
|
10
12
|
export declare function tsNotReadyError(member: string): TeacssEngineError;
|
|
11
13
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.js
CHANGED
|
@@ -11,6 +11,10 @@ export class TeacssEngineError extends Error {
|
|
|
11
11
|
export function tsRequiredError(member) {
|
|
12
12
|
return new TeacssEngineError("E_TS_REQUIRED", `[@teacss/engine] ${member} requires @teacss/core (optional peer) to be installed`, { member });
|
|
13
13
|
}
|
|
14
|
+
/** The generator was disposed; the native Engine reports the same code after its own `dispose()`. */
|
|
15
|
+
export function disposedError(member) {
|
|
16
|
+
return new TeacssEngineError("E_DISPOSED", `[@teacss/engine] ${member} called after dispose()`);
|
|
17
|
+
}
|
|
14
18
|
/** v02.9 §3.3: the member needs the TypeScript engine, which has not been materialized. */
|
|
15
19
|
export function tsNotReadyError(member) {
|
|
16
20
|
return new TeacssEngineError("E_TS_REQUIRED", `[@teacss/engine] ${member} needs the TypeScript engine; await generator[Symbol.for('@teacss/engine/materialize')]() first or set engine: 'ts'`, { member });
|
package/dist/generator.d.ts
CHANGED
|
@@ -19,7 +19,8 @@ export declare function engineStats(): {
|
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* v02.9 §9: each reason and path prints once per process; the counter grows on every call. A
|
|
22
|
-
* host `report(reason, path, level)` (
|
|
22
|
+
* host `report(reason, path, level)` (core's `reportFallback`) gets every call and does both
|
|
23
|
+
* itself, so the counter is not touched here.
|
|
23
24
|
*/
|
|
24
25
|
export declare function reportFallback(reason: string, path: string, host?: FacadeHost, level?: "info" | "warn"): void;
|
|
25
26
|
export declare class FacadeGenerator {
|
|
@@ -121,6 +122,13 @@ export declare class FacadeGenerator {
|
|
|
121
122
|
userConfig: Record<string, unknown>;
|
|
122
123
|
version: number;
|
|
123
124
|
}): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Releases the Engine this generator owns; later `generate`, `parseToken`, `applyExtractors`,
|
|
127
|
+
* `prepareConfig` and `commitConfig` throw `E_DISPOSED`, and a second call does nothing. A
|
|
128
|
+
* candidate committed into another generator handed its Engine over and leaves it alone.
|
|
129
|
+
*/
|
|
130
|
+
dispose(): void;
|
|
131
|
+
[Symbol.dispose](): void;
|
|
124
132
|
}
|
|
125
133
|
/**
|
|
126
134
|
* v02.9 §3.1: a Rust facade, or the reason the configuration needs TypeScript. Errors from
|
|
@@ -140,7 +148,7 @@ export interface FacadeHost {
|
|
|
140
148
|
/** core/utils/warn.ts 的 warnOnce;传入时 shortcut 警告与 TS 引擎共用一个去重集合。 */
|
|
141
149
|
warnOnce?: (message: string) => void;
|
|
142
150
|
} | undefined;
|
|
143
|
-
/**
|
|
151
|
+
/** 挂钩注入的回退出口(core 的 reportFallback):每次回退都调用,由它计数并按 reason 与 path 去重打印;缺省时 facade 自己计数并写 process.stderr。 */
|
|
144
152
|
report?: (reason: string, path: string, level: "info" | "warn") => void;
|
|
145
153
|
}
|
|
146
154
|
export type FacadeCreateResult = {
|
package/dist/generator.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Engine } from "../binding.js";
|
|
|
6
6
|
import { createConfigView } from "./config-view.js";
|
|
7
7
|
import { ENGINE_INSTANCE, ENGINE_MATERIALIZE, ENGINE_PACKAGE_VERSION, ENGINE_STATS } from "./constants.js";
|
|
8
8
|
import { BoundedSet, BoundedTokenCache, CountableSet, copyCountableSet, expandInputGroups, isCountableSet, MAX_RUNTIME_CACHE_ENTRIES } from "./countable-set.js";
|
|
9
|
-
import { tsNotReadyError } from "./errors.js";
|
|
9
|
+
import { disposedError, tsNotReadyError } from "./errors.js";
|
|
10
10
|
import { buildMatched, createFacadeResult, describeUnmatched, fallbackIsTokenShaped, formatUnmatchedError, shortcutWarningMessages, splitMatched, toTuple } from "./result.js";
|
|
11
11
|
import { mergeDefinedConfig, translateConfig } from "./select.js";
|
|
12
12
|
import { createCompileClassTransformer } from "./transformer.js";
|
|
@@ -167,6 +167,47 @@ function sameStringifiedUtils(left, leftRaw, right, rightRaw, escape) {
|
|
|
167
167
|
}
|
|
168
168
|
/** A fresh copy of each tuple, as the oracle's `copyValidatedStringifiedUtils` returns. */
|
|
169
169
|
const copyTuples = (tuples) => tuples.map((tuple) => [...tuple]);
|
|
170
|
+
/**
|
|
171
|
+
* The token list the Engine holds for each module, mirrored from the `updateModule` results, so
|
|
172
|
+
* `generate` can tell whether a set equals `allTokens()` without copying it across NAPI. It
|
|
173
|
+
* belongs to the backend, so a committed candidate keeps the modules it extracted. Holder counts
|
|
174
|
+
* are built on the first question and then follow each changed module.
|
|
175
|
+
*/
|
|
176
|
+
class ModuleTokens {
|
|
177
|
+
#byModule = new Map();
|
|
178
|
+
#holders = null;
|
|
179
|
+
update(id, tokens) {
|
|
180
|
+
if (this.#holders) {
|
|
181
|
+
ModuleTokens.#hold(this.#holders, this.#byModule.get(id) ?? [], -1);
|
|
182
|
+
ModuleTokens.#hold(this.#holders, tokens, 1);
|
|
183
|
+
}
|
|
184
|
+
this.#byModule.set(id, tokens);
|
|
185
|
+
}
|
|
186
|
+
/** Whether `tokens` holds exactly the tokens some module holds. */
|
|
187
|
+
isAll(tokens) {
|
|
188
|
+
if (!this.#holders) {
|
|
189
|
+
this.#holders = new Map();
|
|
190
|
+
for (const list of this.#byModule.values())
|
|
191
|
+
ModuleTokens.#hold(this.#holders, list, 1);
|
|
192
|
+
}
|
|
193
|
+
const holders = this.#holders;
|
|
194
|
+
if (tokens.size !== holders.size)
|
|
195
|
+
return false;
|
|
196
|
+
for (const token of tokens)
|
|
197
|
+
if (!holders.has(token))
|
|
198
|
+
return false;
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
static #hold(holders, tokens, delta) {
|
|
202
|
+
for (const token of tokens) {
|
|
203
|
+
const count = (holders.get(token) ?? 0) + delta;
|
|
204
|
+
if (count === 0)
|
|
205
|
+
holders.delete(token);
|
|
206
|
+
else
|
|
207
|
+
holders.set(token, count);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
170
211
|
/**
|
|
171
212
|
* core/config.ts:26-36: the first entry of each name wins.
|
|
172
213
|
*/
|
|
@@ -191,19 +232,21 @@ export function engineStats() {
|
|
|
191
232
|
const reported = new Set();
|
|
192
233
|
/**
|
|
193
234
|
* v02.9 §9: each reason and path prints once per process; the counter grows on every call. A
|
|
194
|
-
* host `report(reason, path, level)` (
|
|
235
|
+
* host `report(reason, path, level)` (core's `reportFallback`) gets every call and does both
|
|
236
|
+
* itself, so the counter is not touched here.
|
|
195
237
|
*/
|
|
196
238
|
export function reportFallback(reason, path, host = {}, level = "info") {
|
|
239
|
+
if (typeof host.report === "function") {
|
|
240
|
+
host.report(reason, path, level);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
197
243
|
const stats = engineStats();
|
|
198
244
|
stats.fallbacks[reason] = (stats.fallbacks[reason] ?? 0) + 1;
|
|
199
245
|
const key = `${reason}\0${path}`;
|
|
200
246
|
if (reported.has(key))
|
|
201
247
|
return;
|
|
202
248
|
reported.add(key);
|
|
203
|
-
|
|
204
|
-
host.report(reason, path, level);
|
|
205
|
-
else
|
|
206
|
-
process.stderr.write(`[teacss] engine: falling back to the TypeScript engine (${reason} at ${path})\n`);
|
|
249
|
+
process.stderr.write(`[teacss] engine: falling back to the TypeScript engine (${reason} at ${path})\n`);
|
|
207
250
|
}
|
|
208
251
|
/** array-internal.ts:7-13: ownership is rechecked before each read. */
|
|
209
252
|
function* ownArrayValues(array) {
|
|
@@ -260,6 +303,7 @@ export class FacadeGenerator {
|
|
|
260
303
|
disposeEngine(held.engine);
|
|
261
304
|
});
|
|
262
305
|
#backend;
|
|
306
|
+
#disposed = false;
|
|
263
307
|
#held = null;
|
|
264
308
|
#host;
|
|
265
309
|
#tsFallback;
|
|
@@ -279,7 +323,6 @@ export class FacadeGenerator {
|
|
|
279
323
|
#activatedRules = new Set();
|
|
280
324
|
// Declared for the method cards (F7.15-F7.19).
|
|
281
325
|
#warnedUnmatched = new BoundedSet();
|
|
282
|
-
#allTokens = null;
|
|
283
326
|
#configVersion = 0;
|
|
284
327
|
/** Weak, so a prepared config nobody commits does not keep its candidate (and Engine) alive. */
|
|
285
328
|
#prepared = new WeakSet();
|
|
@@ -307,7 +350,7 @@ export class FacadeGenerator {
|
|
|
307
350
|
const own = view.standard?.compileClass === true ? [this.#transformer] : [];
|
|
308
351
|
const list = uniqueNamed([...own, ...transformers]);
|
|
309
352
|
const config = createConfigView({ view, request, presets, merged: mergeDefinedConfig(defaults, userConfig), transformers: list, host, fallback: this.#tsFallback, engine: own.length ? engine : undefined });
|
|
310
|
-
this.#backend = { kind: "rust", engine, request, presets, config, transformer: this.#transformer };
|
|
353
|
+
this.#backend = { kind: "rust", engine, request, presets, config, transformer: this.#transformer, modules: new ModuleTokens() };
|
|
311
354
|
}
|
|
312
355
|
get version() {
|
|
313
356
|
return this.#host.core?.version ?? ENGINE_PACKAGE_VERSION;
|
|
@@ -370,6 +413,7 @@ export class FacadeGenerator {
|
|
|
370
413
|
* tokens; a counted set adds each token's occurrences.
|
|
371
414
|
*/
|
|
372
415
|
async applyExtractors(code, id, extracted = new Set()) {
|
|
416
|
+
this.#assertLive("applyExtractors");
|
|
373
417
|
await Promise.resolve();
|
|
374
418
|
const backend = this.#backend;
|
|
375
419
|
if (backend.kind === "ts")
|
|
@@ -407,6 +451,7 @@ export class FacadeGenerator {
|
|
|
407
451
|
* runs `applyExtractors` on it, generator.ts:2378).
|
|
408
452
|
*/
|
|
409
453
|
async generate(input, options = {}) {
|
|
454
|
+
this.#assertLive("generate");
|
|
410
455
|
const backend = this.#backend;
|
|
411
456
|
if (backend.kind === "ts") {
|
|
412
457
|
// A rule may commit a new configuration through this facade while the TS backend runs; the
|
|
@@ -496,17 +541,12 @@ export class FacadeGenerator {
|
|
|
496
541
|
}
|
|
497
542
|
if (Array.isArray(input) || input instanceof Set) {
|
|
498
543
|
const tokens = expandInputGroups(new Set(input));
|
|
499
|
-
|
|
544
|
+
// v02.9 §7.3: a set equal to every module token is sent as `{ kind: "all" }`.
|
|
545
|
+
const all = this.#backend.modules.isAll(tokens);
|
|
546
|
+
return { rustInput: all ? { kind: "all" } : { kind: "tokens", tokens: [...tokens] }, countOf: () => -1, collection: true, tokens };
|
|
500
547
|
}
|
|
501
548
|
throw new TypeError("[@teacss/engine] generate input must be a string, array, Set or CountableSet");
|
|
502
549
|
}
|
|
503
|
-
/** v02.9 §7.3: a set equal to every module token is sent as `{ kind: "all" }`. */
|
|
504
|
-
#isAllTokens(tokens) {
|
|
505
|
-
const engine = this.#backend.engine;
|
|
506
|
-
this.#allTokens ??= new Set(engine.allTokens());
|
|
507
|
-
const all = this.#allTokens;
|
|
508
|
-
return tokens.size === all.size && [...tokens].every((token) => all.has(token));
|
|
509
|
-
}
|
|
510
550
|
/**
|
|
511
551
|
* The tokens generation visits, in order: the input, then the safelist members it lacks
|
|
512
552
|
* (generator.ts:2390-2410, which adds them without counting).
|
|
@@ -575,6 +615,7 @@ export class FacadeGenerator {
|
|
|
575
615
|
* already cached reads back as `null`. With an `alias` nothing is cached.
|
|
576
616
|
*/
|
|
577
617
|
async parseToken(raw, alias) {
|
|
618
|
+
this.#assertLive("parseToken");
|
|
578
619
|
await Promise.resolve();
|
|
579
620
|
const backend = this.#backend;
|
|
580
621
|
if (backend.kind === "ts")
|
|
@@ -692,6 +733,7 @@ export class FacadeGenerator {
|
|
|
692
733
|
* one. A configuration Rust cannot serve gets a TypeScript candidate.
|
|
693
734
|
*/
|
|
694
735
|
async prepareConfig(userConfig, defaults) {
|
|
736
|
+
this.#assertLive("prepareConfig");
|
|
695
737
|
await Promise.resolve();
|
|
696
738
|
const version = ++this.#configVersion;
|
|
697
739
|
const nextDefaults = defaults ?? this.defaults;
|
|
@@ -712,7 +754,7 @@ export class FacadeGenerator {
|
|
|
712
754
|
this.#prepared.add(prepared);
|
|
713
755
|
const held = candidate.#backend.kind === "rust" ? { kind: "rust", engine: candidate.#backend.engine, committed: false } : { kind: "ts", committed: false };
|
|
714
756
|
candidate.#held = held;
|
|
715
|
-
FacadeGenerator.#registry.register(candidate, held);
|
|
757
|
+
FacadeGenerator.#registry.register(candidate, held, candidate);
|
|
716
758
|
return prepared;
|
|
717
759
|
}
|
|
718
760
|
/**
|
|
@@ -720,6 +762,7 @@ export class FacadeGenerator {
|
|
|
720
762
|
* superseded Rust candidate is disposed; so is the previous Engine once it is replaced.
|
|
721
763
|
*/
|
|
722
764
|
commitConfig(prepared) {
|
|
765
|
+
this.#assertLive("commitConfig");
|
|
723
766
|
if (!this.#prepared.delete(prepared))
|
|
724
767
|
return false;
|
|
725
768
|
const candidate = prepared.generator;
|
|
@@ -736,13 +779,36 @@ export class FacadeGenerator {
|
|
|
736
779
|
this.#backend = candidate.#backend;
|
|
737
780
|
if (candidate.#held)
|
|
738
781
|
candidate.#held.committed = true;
|
|
739
|
-
this.#allTokens = null;
|
|
740
782
|
this.#tsFallback.invalidate(prepared.userConfig, prepared.defaults);
|
|
741
783
|
if (previous.kind === "rust" && (this.#backend.kind !== "rust" || previous.engine !== this.#backend.engine))
|
|
742
784
|
disposeEngine(previous.engine);
|
|
743
785
|
this.#dispatchConfig(this.config);
|
|
744
786
|
return true;
|
|
745
787
|
}
|
|
788
|
+
/**
|
|
789
|
+
* Releases the Engine this generator owns; later `generate`, `parseToken`, `applyExtractors`,
|
|
790
|
+
* `prepareConfig` and `commitConfig` throw `E_DISPOSED`, and a second call does nothing. A
|
|
791
|
+
* candidate committed into another generator handed its Engine over and leaves it alone.
|
|
792
|
+
*/
|
|
793
|
+
dispose() {
|
|
794
|
+
if (this.#disposed)
|
|
795
|
+
return;
|
|
796
|
+
this.#disposed = true;
|
|
797
|
+
FacadeGenerator.#registry.unregister(this);
|
|
798
|
+
const backend = this.#backend;
|
|
799
|
+
if (backend.kind !== "rust")
|
|
800
|
+
return;
|
|
801
|
+
const handedOver = this.#held?.committed === true && this.#held.engine === backend.engine;
|
|
802
|
+
if (!handedOver)
|
|
803
|
+
disposeEngine(backend.engine);
|
|
804
|
+
}
|
|
805
|
+
[Symbol.dispose]() {
|
|
806
|
+
this.dispose();
|
|
807
|
+
}
|
|
808
|
+
#assertLive(member) {
|
|
809
|
+
if (this.#disposed)
|
|
810
|
+
throw disposedError(member);
|
|
811
|
+
}
|
|
746
812
|
/** An explicit `engine: "rust"` asked for Rust, so its fallback is a warning. */
|
|
747
813
|
#reportFallback(failure) {
|
|
748
814
|
const explicit = this.defaults?.engine === "rust" || this.userConfig?.engine === "rust";
|
|
@@ -797,13 +863,12 @@ export class FacadeGenerator {
|
|
|
797
863
|
}
|
|
798
864
|
catch { }
|
|
799
865
|
}
|
|
800
|
-
/** A changed module invalidates the `allTokens` snapshot. */
|
|
801
866
|
#updateModule(id, code) {
|
|
802
867
|
if (this.#backend.kind !== "rust")
|
|
803
868
|
return [];
|
|
804
869
|
const result = this.#backend.engine.updateModule(id, code);
|
|
805
870
|
if (result.changed)
|
|
806
|
-
this.#
|
|
871
|
+
this.#backend.modules.update(id, result.tokens);
|
|
807
872
|
return result.tokens;
|
|
808
873
|
}
|
|
809
874
|
}
|
package/dist/select.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare function pick(obj: Record<string, unknown>, keys: Iterable<string
|
|
|
54
54
|
export declare function translateTaggedPreset(preset: object, path: string, ctx: {
|
|
55
55
|
hasEntry: boolean;
|
|
56
56
|
}): Success<object | null> | Failure | undefined;
|
|
57
|
-
/** Keys of an unmarked preset whose non-empty value means fallback
|
|
57
|
+
/** Keys of an unmarked preset whose non-empty value means fallback; `content` is checked by `hasContentBeyondPipeline`. */
|
|
58
58
|
export declare const PRESET_DYNAMIC_KEYS: readonly string[];
|
|
59
59
|
/**
|
|
60
60
|
* v02.9 §4.5: the static shortcut forms as `[name, expansion]` pairs. A shortcut meta (`[n, e, meta]`)
|
package/dist/select.js
CHANGED
|
@@ -223,11 +223,23 @@ export function translateTaggedPreset(preset, path, ctx) {
|
|
|
223
223
|
return ctx.hasEntry ? ok(null) : fail("role-palettes-without-entry", path);
|
|
224
224
|
return undefined;
|
|
225
225
|
}
|
|
226
|
-
/** Keys of an unmarked preset whose non-empty value means fallback
|
|
227
|
-
export const PRESET_DYNAMIC_KEYS = Object.freeze(["rules", "variants", "extractors", "preflights", "preprocess", "postprocess", "extendTheme", "configResolved", "transformers", "autocomplete", "extractorDefault"
|
|
226
|
+
/** Keys of an unmarked preset whose non-empty value means fallback; `content` is checked by `hasContentBeyondPipeline`. */
|
|
227
|
+
export const PRESET_DYNAMIC_KEYS = Object.freeze(["rules", "variants", "extractors", "preflights", "preprocess", "postprocess", "extendTheme", "configResolved", "transformers", "autocomplete", "extractorDefault"]);
|
|
228
228
|
const isPlainObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
229
229
|
/** Values `undefined` are left out. */
|
|
230
230
|
const defined = (entries) => Object.fromEntries(Object.entries(entries).filter(([, value]) => value !== undefined));
|
|
231
|
+
/**
|
|
232
|
+
* `content.pipeline` only filters the modules an integration feeds in; generation never reads it
|
|
233
|
+
* (v02.2 §4), so it stays in the config view and never reaches Rust. Any other content field of a
|
|
234
|
+
* preset is not translated.
|
|
235
|
+
*/
|
|
236
|
+
function hasContentBeyondPipeline(content) {
|
|
237
|
+
if (!isNonEmpty(content))
|
|
238
|
+
return false;
|
|
239
|
+
if (!isPlainObject(content))
|
|
240
|
+
return true;
|
|
241
|
+
return Object.keys(content).some((key) => key !== "pipeline" && isNonEmpty(content[key]));
|
|
242
|
+
}
|
|
231
243
|
/**
|
|
232
244
|
* v02.9 §4.5: the static shortcut forms as `[name, expansion]` pairs. A shortcut meta (`[n, e, meta]`)
|
|
233
245
|
* has no place in `StaticPreset.shortcuts`, so any meta key falls back.
|
|
@@ -354,6 +366,8 @@ export function translateStaticPreset(preset, path) {
|
|
|
354
366
|
if (isNonEmpty(preset[key]))
|
|
355
367
|
return fail(`preset.${key}`, `${path}.${key}`);
|
|
356
368
|
}
|
|
369
|
+
if (hasContentBeyondPipeline(preset.content))
|
|
370
|
+
return fail("preset.content", `${path}.content`);
|
|
357
371
|
const shortcuts = translateShortcuts(preset.shortcuts, `${path}.shortcuts`, "preset.shortcuts");
|
|
358
372
|
if (!shortcuts.ok)
|
|
359
373
|
return shortcuts;
|
|
@@ -401,8 +415,6 @@ export function translateInline(merged) {
|
|
|
401
415
|
if (merged.content !== undefined) {
|
|
402
416
|
if (!isPlainObject(merged.content))
|
|
403
417
|
return fail("content", "content");
|
|
404
|
-
if (Object.hasOwn(merged.content, "pipeline") && merged.content.pipeline !== undefined)
|
|
405
|
-
return fail("content.pipeline", "content.pipeline");
|
|
406
418
|
if (isNonEmpty(merged.content.inline))
|
|
407
419
|
return fail("content.inline", "content.inline");
|
|
408
420
|
const filesystem = merged.content.filesystem;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teacss/engine",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "In-process Rust engine for TeaCSS 0.9 (napi-rs binding and 0.8.x-compatible facade)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -65,21 +65,21 @@
|
|
|
65
65
|
},
|
|
66
66
|
"engineCompat": {
|
|
67
67
|
"core": ">=0.8.5 <0.10.0",
|
|
68
|
-
"defaultMode": "
|
|
68
|
+
"defaultMode": "auto",
|
|
69
69
|
"oracle": {
|
|
70
70
|
"teacssTs": "0.8.5",
|
|
71
71
|
"commit": "786b4d40"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
"optionalDependencies": {
|
|
75
|
-
"@teacss/engine-darwin-arm64": "0.9.
|
|
76
|
-
"@teacss/engine-darwin-x64": "0.9.
|
|
77
|
-
"@teacss/engine-linux-arm64-gnu": "0.9.
|
|
78
|
-
"@teacss/engine-linux-arm64-musl": "0.9.
|
|
79
|
-
"@teacss/engine-linux-x64-gnu": "0.9.
|
|
80
|
-
"@teacss/engine-linux-x64-musl": "0.9.
|
|
81
|
-
"@teacss/engine-win32-arm64-msvc": "0.9.
|
|
82
|
-
"@teacss/engine-win32-x64-msvc": "0.9.
|
|
75
|
+
"@teacss/engine-darwin-arm64": "0.9.2",
|
|
76
|
+
"@teacss/engine-darwin-x64": "0.9.2",
|
|
77
|
+
"@teacss/engine-linux-arm64-gnu": "0.9.2",
|
|
78
|
+
"@teacss/engine-linux-arm64-musl": "0.9.2",
|
|
79
|
+
"@teacss/engine-linux-x64-gnu": "0.9.2",
|
|
80
|
+
"@teacss/engine-linux-x64-musl": "0.9.2",
|
|
81
|
+
"@teacss/engine-win32-arm64-msvc": "0.9.2",
|
|
82
|
+
"@teacss/engine-win32-x64-msvc": "0.9.2"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
85
|
"@teacss/config": ">=0.8.5 <0.10.0 || >=0.9.0-alpha.0 <0.10.0",
|