@griffel/transform 3.0.5 → 3.0.6

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 (188) hide show
  1. package/LICENSE.md +21 -0
  2. package/package.json +6 -5
  3. package/src/constants.d.mts +2 -0
  4. package/src/{constants.mts → constants.mjs} +1 -0
  5. package/src/constants.mjs.map +1 -0
  6. package/src/evaluation/astEvaluator.d.mts +20 -0
  7. package/src/evaluation/astEvaluator.mjs +90 -0
  8. package/src/evaluation/astEvaluator.mjs.map +1 -0
  9. package/src/evaluation/batchEvaluator.d.mts +13 -0
  10. package/src/evaluation/batchEvaluator.mjs +54 -0
  11. package/src/evaluation/batchEvaluator.mjs.map +1 -0
  12. package/src/evaluation/evalCache.d.mts +9 -0
  13. package/src/evaluation/evalCache.mjs +65 -0
  14. package/src/evaluation/evalCache.mjs.map +1 -0
  15. package/src/evaluation/fluentTokensPlugin.d.mts +2 -0
  16. package/src/evaluation/fluentTokensPlugin.mjs +70 -0
  17. package/src/evaluation/fluentTokensPlugin.mjs.map +1 -0
  18. package/src/evaluation/module.d.mts +44 -0
  19. package/src/evaluation/module.mjs +207 -0
  20. package/src/evaluation/module.mjs.map +1 -0
  21. package/src/evaluation/process.d.mts +24 -0
  22. package/src/evaluation/{process.mts → process.mjs} +7 -12
  23. package/src/evaluation/process.mjs.map +1 -0
  24. package/src/evaluation/types.d.mts +34 -0
  25. package/src/evaluation/types.mjs +2 -0
  26. package/src/evaluation/types.mjs.map +1 -0
  27. package/src/evaluation/vmEvaluator.d.mts +3 -0
  28. package/src/evaluation/vmEvaluator.mjs +33 -0
  29. package/src/evaluation/vmEvaluator.mjs.map +1 -0
  30. package/src/{index.mts → index.d.mts} +0 -4
  31. package/src/index.mjs +9 -0
  32. package/src/index.mjs.map +1 -0
  33. package/src/transformSync.d.mts +41 -0
  34. package/src/transformSync.mjs +253 -0
  35. package/src/transformSync.mjs.map +1 -0
  36. package/src/types.d.mts +12 -0
  37. package/src/types.mjs +2 -0
  38. package/src/types.mjs.map +1 -0
  39. package/src/utils/convertESMtoCJS.d.mts +6 -0
  40. package/src/utils/convertESMtoCJS.mjs +203 -0
  41. package/src/utils/convertESMtoCJS.mjs.map +1 -0
  42. package/src/utils/dedupeCSSRules.d.mts +6 -0
  43. package/src/utils/dedupeCSSRules.mjs +19 -0
  44. package/src/utils/dedupeCSSRules.mjs.map +1 -0
  45. package/CHANGELOG.json +0 -404
  46. package/CHANGELOG.md +0 -130
  47. package/__fixtures__/assets/blank.jpg +0 -0
  48. package/__fixtures__/assets/code.ts +0 -12
  49. package/__fixtures__/assets/empty.jpg +0 -0
  50. package/__fixtures__/assets/output.meta.json +0 -12
  51. package/__fixtures__/assets/output.ts +0 -12
  52. package/__fixtures__/assets-multiple-declarations/blank.jpg +0 -0
  53. package/__fixtures__/assets-multiple-declarations/code.ts +0 -8
  54. package/__fixtures__/assets-multiple-declarations/empty.jpg +0 -0
  55. package/__fixtures__/assets-multiple-declarations/output.meta.json +0 -9
  56. package/__fixtures__/assets-multiple-declarations/output.ts +0 -6
  57. package/__fixtures__/assets-reset-styles/blank.jpg +0 -0
  58. package/__fixtures__/assets-reset-styles/code.ts +0 -11
  59. package/__fixtures__/assets-reset-styles/empty.jpg +0 -0
  60. package/__fixtures__/assets-reset-styles/output.meta.json +0 -11
  61. package/__fixtures__/assets-reset-styles/output.ts +0 -7
  62. package/__fixtures__/assets-urls/code.ts +0 -13
  63. package/__fixtures__/assets-urls/output.meta.json +0 -14
  64. package/__fixtures__/assets-urls/output.ts +0 -10
  65. package/__fixtures__/at-rules/code.ts +0 -14
  66. package/__fixtures__/at-rules/output.meta.json +0 -15
  67. package/__fixtures__/at-rules/output.ts +0 -10
  68. package/__fixtures__/config-classname-hash-salt/code.ts +0 -5
  69. package/__fixtures__/config-classname-hash-salt/output.meta.json +0 -7
  70. package/__fixtures__/config-classname-hash-salt/output.ts +0 -3
  71. package/__fixtures__/config-evaluation-rules/code.ts +0 -8
  72. package/__fixtures__/config-evaluation-rules/consts.ts +0 -1
  73. package/__fixtures__/config-evaluation-rules/output.meta.json +0 -7
  74. package/__fixtures__/config-evaluation-rules/output.ts +0 -4
  75. package/__fixtures__/config-evaluation-rules/sampleEvaluator.cjs +0 -12
  76. package/__fixtures__/error-argument-count/fixture.js +0 -4
  77. package/__fixtures__/error-cjs/fixture.js +0 -4
  78. package/__fixtures__/error-on-undefined/fixture.ts +0 -7
  79. package/__fixtures__/error-on-undefined/tokens.ts +0 -1
  80. package/__fixtures__/export-default/code.ts +0 -6
  81. package/__fixtures__/export-default/output.meta.json +0 -14
  82. package/__fixtures__/export-default/output.ts +0 -6
  83. package/__fixtures__/function-mixin/code.ts +0 -6
  84. package/__fixtures__/function-mixin/mixins.ts +0 -7
  85. package/__fixtures__/function-mixin/output.meta.json +0 -7
  86. package/__fixtures__/function-mixin/output.ts +0 -4
  87. package/__fixtures__/function-mixin/tokens.ts +0 -3
  88. package/__fixtures__/import-alias/code.ts +0 -5
  89. package/__fixtures__/import-alias/output.meta.json +0 -7
  90. package/__fixtures__/import-alias/output.ts +0 -3
  91. package/__fixtures__/import-custom-module/code.ts +0 -6
  92. package/__fixtures__/import-custom-module/output.meta.json +0 -7
  93. package/__fixtures__/import-custom-module/output.ts +0 -4
  94. package/__fixtures__/keyframes/code.ts +0 -22
  95. package/__fixtures__/keyframes/output.meta.json +0 -17
  96. package/__fixtures__/keyframes/output.ts +0 -6
  97. package/__fixtures__/multiple-declarations/code.ts +0 -8
  98. package/__fixtures__/multiple-declarations/output.meta.json +0 -7
  99. package/__fixtures__/multiple-declarations/output.ts +0 -4
  100. package/__fixtures__/non-existing-module-call/code.ts +0 -10
  101. package/__fixtures__/non-existing-module-call/module.ts +0 -13
  102. package/__fixtures__/non-existing-module-call/output.meta.json +0 -7
  103. package/__fixtures__/non-existing-module-call/output.ts +0 -6
  104. package/__fixtures__/object/code.ts +0 -6
  105. package/__fixtures__/object/output.meta.json +0 -14
  106. package/__fixtures__/object/output.ts +0 -6
  107. package/__fixtures__/object-computed-keys/code.ts +0 -8
  108. package/__fixtures__/object-computed-keys/output.meta.json +0 -14
  109. package/__fixtures__/object-computed-keys/output.ts +0 -8
  110. package/__fixtures__/object-imported-keys/code.ts +0 -9
  111. package/__fixtures__/object-imported-keys/consts.ts +0 -2
  112. package/__fixtures__/object-imported-keys/output.meta.json +0 -7
  113. package/__fixtures__/object-imported-keys/output.ts +0 -4
  114. package/__fixtures__/object-mixins/code.ts +0 -11
  115. package/__fixtures__/object-mixins/mixins.ts +0 -17
  116. package/__fixtures__/object-mixins/output.meta.json +0 -16
  117. package/__fixtures__/object-mixins/output.ts +0 -10
  118. package/__fixtures__/object-mixins/tokens.ts +0 -3
  119. package/__fixtures__/object-nesting/code.ts +0 -13
  120. package/__fixtures__/object-nesting/consts.ts +0 -1
  121. package/__fixtures__/object-nesting/output.meta.json +0 -9
  122. package/__fixtures__/object-nesting/output.ts +0 -6
  123. package/__fixtures__/object-reset/code.ts +0 -8
  124. package/__fixtures__/object-reset/output.meta.json +0 -7
  125. package/__fixtures__/object-reset/output.ts +0 -5
  126. package/__fixtures__/object-sequence-expr/code.ts +0 -16
  127. package/__fixtures__/object-sequence-expr/output.meta.json +0 -7
  128. package/__fixtures__/object-sequence-expr/output.ts +0 -7
  129. package/__fixtures__/object-shorthands/code.ts +0 -8
  130. package/__fixtures__/object-shorthands/output.meta.json +0 -20
  131. package/__fixtures__/object-shorthands/output.ts +0 -5
  132. package/__fixtures__/object-variables/code.ts +0 -9
  133. package/__fixtures__/object-variables/output.meta.json +0 -15
  134. package/__fixtures__/object-variables/output.ts +0 -9
  135. package/__fixtures__/object-variables/vars.ts +0 -5
  136. package/__fixtures__/reset-styles/code.ts +0 -6
  137. package/__fixtures__/reset-styles/output.meta.json +0 -7
  138. package/__fixtures__/reset-styles/output.ts +0 -3
  139. package/__fixtures__/reset-styles-at-rules/code.ts +0 -7
  140. package/__fixtures__/reset-styles-at-rules/output.meta.json +0 -8
  141. package/__fixtures__/reset-styles-at-rules/output.ts +0 -3
  142. package/__fixtures__/rules-with-metadata/code.ts +0 -9
  143. package/__fixtures__/rules-with-metadata/output.meta.json +0 -14
  144. package/__fixtures__/rules-with-metadata/output.ts +0 -3
  145. package/__fixtures__/shared-mixins/code.ts +0 -7
  146. package/__fixtures__/shared-mixins/mixins.ts +0 -6
  147. package/__fixtures__/shared-mixins/output.meta.json +0 -7
  148. package/__fixtures__/shared-mixins/output.ts +0 -8
  149. package/__fixtures__/static-styles/code.ts +0 -7
  150. package/__fixtures__/static-styles/output.meta.json +0 -7
  151. package/__fixtures__/static-styles/output.ts +0 -3
  152. package/__fixtures__/static-styles-array/code.ts +0 -10
  153. package/__fixtures__/static-styles-array/output.meta.json +0 -7
  154. package/__fixtures__/static-styles-array/output.ts +0 -3
  155. package/__fixtures__/static-styles-string/code.ts +0 -3
  156. package/__fixtures__/static-styles-string/output.meta.json +0 -7
  157. package/__fixtures__/static-styles-string/output.ts +0 -3
  158. package/__fixtures__/tokens/code.ts +0 -11
  159. package/__fixtures__/tokens/output.meta.json +0 -12
  160. package/__fixtures__/tokens/output.ts +0 -7
  161. package/__fixtures__/tokens/tokens.ts +0 -4
  162. package/__fixtures__/unsupported-css-properties/fixture.ts +0 -16
  163. package/__fixtures__/unsupported-css-properties/output.meta.json +0 -5
  164. package/__fixtures__/unsupported-css-properties/output.ts +0 -3
  165. package/eslint.config.mjs +0 -31
  166. package/project.json +0 -51
  167. package/src/evaluation/astEvaluator.mts +0 -109
  168. package/src/evaluation/astEvaluator.test.mts +0 -126
  169. package/src/evaluation/batchEvaluator.mts +0 -79
  170. package/src/evaluation/evalCache.mts +0 -84
  171. package/src/evaluation/fluentTokensPlugin.mts +0 -82
  172. package/src/evaluation/fluentTokensPlugin.test.mts +0 -130
  173. package/src/evaluation/module.mts +0 -271
  174. package/src/evaluation/module.test.mts +0 -133
  175. package/src/evaluation/types.mts +0 -49
  176. package/src/evaluation/vmEvaluator.mts +0 -45
  177. package/src/evaluation/vmEvaluator.test.mts +0 -30
  178. package/src/transformSync.mts +0 -425
  179. package/src/transformSync.test.mts +0 -429
  180. package/src/types.mts +0 -13
  181. package/src/utils/convertESMtoCJS.mts +0 -226
  182. package/src/utils/convertESMtoCJS.test.mts +0 -159
  183. package/src/utils/dedupeCSSRules.mts +0 -25
  184. package/src/utils/dedupeCSSRules.test.mts +0 -39
  185. package/tsconfig.json +0 -19
  186. package/tsconfig.lib.json +0 -30
  187. package/tsconfig.spec.json +0 -24
  188. package/vitest.config.mts +0 -18
@@ -1,271 +0,0 @@
1
- /**
2
- * Custom module system for evaluating code in a sandboxed VM context.
3
- * Copied from @linaria/babel-preset v3.0.0-beta.19, adapted to use `debug` package
4
- * and local imports instead of @linaria/* packages.
5
- *
6
- * This serves 2 purposes:
7
- * - Avoid leakage from evaluated code to module cache in current context, e.g. `babel-register`
8
- * - Allow us to invalidate the module cache without affecting other stuff, necessary for rebuilds
9
- *
10
- * We also use it to transpile the code with Babel by default.
11
- * We also store source maps for it to provide correct error stacktraces.
12
- */
13
-
14
- import fs from 'node:fs';
15
- import NativeModule from 'node:module';
16
- import path from 'node:path';
17
- import vm from 'node:vm';
18
- import createDebug from 'debug';
19
-
20
- import { ASSET_TAG_OPEN, ASSET_TAG_CLOSE } from '../constants.mjs';
21
- import { convertESMtoCJS } from '../utils/convertESMtoCJS.mjs';
22
- import * as EvalCache from './evalCache.mjs';
23
- import * as mockProcess from './process.mjs';
24
- import type { EvalRule } from './types.mjs';
25
-
26
- export type TransformResolver = (
27
- id: string,
28
- options: { filename: string; paths: readonly string[] },
29
- ) => { path: string; builtin: boolean };
30
-
31
- const debug = createDebug('griffel:module');
32
-
33
- // Separate cache for evaluated modules
34
- let cache: Record<string, Module> = {};
35
-
36
- const NOOP = () => { /* noop */ };
37
-
38
- /** Checks if a value is an Error-like object (works across VM contexts where `instanceof Error` fails). */
39
- function isError(e: unknown): e is Error {
40
- return e !== null && e !== undefined && typeof e === 'object' && 'message' in e && 'stack' in e;
41
- }
42
-
43
- const createCustomDebug =
44
- (depth: number) =>
45
- (namespaces: string, arg1: unknown, ...args: unknown[]) => {
46
- const modulePrefix = depth === 0 ? 'module' : `sub-module-${depth}`;
47
- debug(`${modulePrefix}:${namespaces}`, arg1, ...args);
48
- };
49
-
50
- export class Module {
51
- readonly id: string;
52
- readonly filename: string;
53
- declare readonly paths: readonly string[];
54
- rules: EvalRule[];
55
- imports: Map<string, string[]> | null = null;
56
- dependencies: string[] | null = null;
57
- transform: ((code: string, filename: string) => string) | null = null;
58
- static readonly extensions = new Set(['.json', '.js', '.jsx', '.ts', '.tsx', '.cjs', '.mjs', '.mts', '.cts']);
59
-
60
- exports: unknown = {};
61
-
62
- private readonly resolveFilename: TransformResolver;
63
- private debug: (namespaces: string, arg1: unknown, ...args: unknown[]) => void;
64
- private debuggerDepth: number;
65
-
66
- constructor(filename: string, rules: EvalRule[], resolveFilename: TransformResolver, debuggerDepth = 0) {
67
- this.id = filename;
68
- this.filename = filename;
69
- this.rules = rules;
70
- this.resolveFilename = resolveFilename;
71
- this.debuggerDepth = debuggerDepth;
72
- this.debug = createCustomDebug(debuggerDepth);
73
-
74
- Object.defineProperties(this, {
75
- id: {
76
- value: filename,
77
- writable: false,
78
- },
79
- filename: {
80
- value: filename,
81
- writable: false,
82
- },
83
- paths: {
84
- value: Object.freeze(
85
- (NativeModule as unknown as { _nodeModulePaths: (dir: string) => string[] })._nodeModulePaths(
86
- path.dirname(filename),
87
- ),
88
- ),
89
- writable: false,
90
- },
91
- });
92
-
93
- this.exports = {};
94
- this.debug('prepare', filename);
95
- }
96
-
97
- require: ((id: string) => unknown) & {
98
- ensure: () => void;
99
- cache: Record<string, Module>;
100
- resolve: (id: string) => string;
101
- } = Object.assign(
102
- (id: string): unknown => {
103
- this.debug('require', id);
104
-
105
- // Resolve module id (and filename) relatively to parent module
106
- const resolved = this.resolveFilename(id, this);
107
-
108
- if (resolved.builtin) {
109
- throw new Error(`Unable to import "${id}". Importing Node builtins is not supported in the sandbox.`);
110
- }
111
-
112
- const filename = resolved.path;
113
-
114
- this.dependencies?.push(id);
115
- let cacheKey = filename;
116
- let only: string[] = [];
117
-
118
- if (this.imports?.has(id)) {
119
- // We know what exactly we need from this module. Let's shake it!
120
- only = this.imports.get(id)!.sort();
121
-
122
- if (only.length === 0) {
123
- // Probably the module is used as a value itself
124
- // like `'The answer is ' + require('./module')`
125
- only = ['default'];
126
- }
127
-
128
- cacheKey += `:${only.join(',')}`;
129
- }
130
-
131
- let m = cache[cacheKey];
132
-
133
- if (!m) {
134
- this.debug('cached:not-exist', id);
135
-
136
- // Create the module if cached module is not available
137
- m = new Module(filename, this.rules, this.resolveFilename, this.debuggerDepth + 1);
138
- m.transform = this.transform;
139
- // Store it in cache at this point, otherwise
140
- // we would end up in infinite loop with cyclic dependencies
141
- cache[cacheKey] = m;
142
-
143
- const ext = path.extname(filename).toLowerCase();
144
-
145
- if (Module.extensions.has(ext)) {
146
- // To evaluate the file, we need to read it first
147
- const code = fs.readFileSync(filename, 'utf-8');
148
-
149
- if (ext === '.json') {
150
- // For JSON files, parse it to a JS object similar to Node
151
- m.exports = JSON.parse(code);
152
- } else {
153
- // For JS/TS files, evaluate the module
154
- // The module will be transpiled using provided transform
155
- m.evaluate(code, only.includes('*') ? ['*'] : only);
156
- }
157
- } else {
158
- // For non JS/JSON requires, export the resolved absolute path wrapped in asset tags.
159
- // This allows downstream tools (e.g. webpack plugin) to resolve the path correctly
160
- // when CSS is extracted to a different location.
161
- m.exports = ASSET_TAG_OPEN + filename + ASSET_TAG_CLOSE;
162
- }
163
- } else {
164
- this.debug('cached:exist', id);
165
- }
166
-
167
- return m.exports;
168
- },
169
- {
170
- ensure: NOOP,
171
- cache,
172
- resolve: (id: string) => this.resolveFilename(id, this).path,
173
- },
174
- );
175
-
176
- evaluate(text: string, only: string[] | null = null, useEvalCache = true): void {
177
- const { filename } = this;
178
- // Find last matching rule (iterate backwards, break on first match)
179
- let action: EvalRule['action'] = 'ignore';
180
-
181
- for (let i = this.rules.length - 1; i >= 0; i--) {
182
- const { test } = this.rules[i];
183
-
184
- if (!test || (typeof test === 'function' ? test(filename) : test.test(filename))) {
185
- action = this.rules[i].action;
186
- break;
187
- }
188
- }
189
-
190
- const cacheKey = [this.filename, ...(only ?? [])];
191
-
192
- if (useEvalCache && EvalCache.has(cacheKey, text)) {
193
- this.exports = EvalCache.get(cacheKey, text);
194
- return;
195
- }
196
-
197
- let code: string;
198
-
199
- if (action === 'ignore') {
200
- this.debug('ignore', `${filename}`);
201
- code = text;
202
- } else {
203
- // For JavaScript files, we need to transpile it and to get the exports of the module
204
- this.debug('prepare-evaluation', this.filename, 'using', action.name);
205
-
206
- const result = action(this.filename, text, only);
207
-
208
- code = result.code;
209
- this.imports = result.imports;
210
-
211
- // Convert ESM syntax to CJS so it can run inside a function wrapper in vm.Script
212
- if (result.moduleKind === 'esm') {
213
- code = convertESMtoCJS(code, this.filename);
214
- }
215
-
216
- this.debug('evaluate', `${this.filename} (only ${(only || []).join(', ')}):\n${code}`);
217
- }
218
-
219
- const script = new vm.Script(`(function (exports) { ${code}\n})(exports);`, {
220
- filename: this.filename,
221
- });
222
-
223
- try {
224
- script.runInContext(
225
- vm.createContext({
226
- clearImmediate: NOOP,
227
- clearInterval: NOOP,
228
- clearTimeout: NOOP,
229
- setImmediate: NOOP,
230
- setInterval: NOOP,
231
- setTimeout: NOOP,
232
- fetch: NOOP,
233
- global,
234
- process: mockProcess,
235
- module: this,
236
- exports: this.exports,
237
- require: this.require,
238
- __filename: this.filename,
239
- __dirname: path.dirname(this.filename),
240
- }),
241
- );
242
- } catch (vmError: unknown) {
243
- // Errors thrown inside vm.runInContext() use the VM context's Error constructor,
244
- // so they fail `instanceof Error` in the host context (e.g. webpack wraps them as NonErrorEmittedError).
245
- // Re-create as a host Error with filename context.
246
- const message = isError(vmError) ? vmError.message : String(vmError);
247
- const hostError = new Error(message);
248
-
249
- if (isError(vmError)) {
250
- hostError.stack = vmError.stack;
251
- }
252
-
253
- throw hostError;
254
- }
255
-
256
- if (useEvalCache) {
257
- EvalCache.set(cacheKey, text, this.exports);
258
- }
259
- }
260
-
261
- static invalidate = (): void => {
262
- cache = {};
263
- };
264
-
265
- static invalidateEvalCache = (): void => {
266
- EvalCache.clear();
267
- };
268
-
269
- static _nodeModulePaths = (filename: string): string[] =>
270
- (NativeModule as unknown as { _nodeModulePaths: (dir: string) => string[] })._nodeModulePaths(filename);
271
- }
@@ -1,133 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import NativeModule from 'node:module';
3
- import * as os from 'node:os';
4
- import * as path from 'node:path';
5
- import { afterEach, describe, expect, it } from 'vitest';
6
-
7
- import { ASSET_TAG_OPEN, ASSET_TAG_CLOSE } from '../constants.mjs';
8
- import { Module } from './module.mjs';
9
- import type { TransformResolver } from './module.mjs';
10
-
11
- const defaultRules = [{ action: 'ignore' as const }];
12
- const defaultResolve: TransformResolver = (id, opts) => ({
13
- path: (NativeModule as unknown as { _resolveFilename: (id: string, options: unknown) => string })._resolveFilename(
14
- id,
15
- opts,
16
- ),
17
- builtin: false,
18
- });
19
-
20
- describe('Module', () => {
21
- let tmpDir: string;
22
-
23
- afterEach(() => {
24
- Module.invalidate();
25
-
26
- if (tmpDir) {
27
- fs.rmSync(tmpDir, { recursive: true, force: true });
28
- }
29
- });
30
-
31
- describe('evaluate', () => {
32
- it('wraps VM errors as host Error with filename context', () => {
33
- tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'griffel-module-test-')));
34
-
35
- const childFile = path.join(tmpDir, 'child.js');
36
- fs.writeFileSync(childFile, 'const x = undefined;\nx.foo;');
37
-
38
- const entryFile = path.join(tmpDir, 'entry.js');
39
- fs.writeFileSync(entryFile, '');
40
-
41
- const m = new Module(entryFile, defaultRules, defaultResolve);
42
-
43
- try {
44
- m.evaluate(`const child = require("./child.js");`, ['child']);
45
- expect.unreachable('should have thrown');
46
- } catch (e) {
47
- // Must be a proper host Error instance (not a VM context Error that webpack wraps as NonErrorEmittedError)
48
- expect(e).toBeInstanceOf(Error);
49
-
50
- const err = e as Error;
51
- // Replace machine-specific paths and line numbers so snapshots are stable across environments
52
- const repoRoot = path.resolve(__dirname, '../../../..');
53
- const normalize = (s: string) =>
54
- s
55
- .split(tmpDir).join('<tmpDir>')
56
- .split(repoRoot).join('<repo>')
57
- .replace(/:\d+(:\d+)?/g, ':<line>');
58
-
59
- expect(normalize(err.message)).toMatchInlineSnapshot(
60
- `"Cannot read properties of undefined (reading 'foo')"`,
61
- );
62
- expect(normalize(err.stack!)).toMatchInlineSnapshot(`
63
- "<repo>/packages/transform/src/evaluation/module.mts:<line>
64
- throw hostError;
65
- ^
66
-
67
- <tmpDir>/child.js:<line>
68
- x.foo;
69
- ^
70
-
71
- TypeError: Cannot read properties of undefined (reading 'foo')
72
- at <tmpDir>/child.js:<line>
73
- at <tmpDir>/child.js:<line>
74
- at Script.runInContext (node:vm:<line>)
75
- at Module.evaluate (<repo>/packages/transform/src/evaluation/module.mts:<line>)
76
- at require.Object.assign.ensure (<repo>/packages/transform/src/evaluation/module.mts:<line>)
77
- at <tmpDir>/entry.js:<line>
78
- at <tmpDir>/entry.js:<line>
79
- at Script.runInContext (node:vm:<line>)
80
- at Module.evaluate (<repo>/packages/transform/src/evaluation/module.mts:<line>)
81
- at <repo>/packages/transform/src/evaluation/module.test.mts:<line>"
82
- `);
83
- }
84
- });
85
- });
86
-
87
- describe('require (asset handling)', () => {
88
- it('wraps non-JS/JSON requires with asset tags containing absolute path', () => {
89
- tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'griffel-module-test-')));
90
-
91
- const jpgFile = path.join(tmpDir, 'test.jpg');
92
- fs.writeFileSync(jpgFile, '');
93
-
94
- const entryFile = path.join(tmpDir, 'entry.js');
95
- fs.writeFileSync(entryFile, '');
96
-
97
- const m = new Module(entryFile, defaultRules, defaultResolve);
98
- const result = m.require('./test.jpg');
99
-
100
- expect(result).toBe(ASSET_TAG_OPEN + jpgFile + ASSET_TAG_CLOSE);
101
- });
102
-
103
- it('wraps .png requires with asset tags', () => {
104
- tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'griffel-module-test-')));
105
-
106
- const pngFile = path.join(tmpDir, 'icon.png');
107
- fs.writeFileSync(pngFile, '');
108
-
109
- const entryFile = path.join(tmpDir, 'entry.js');
110
- fs.writeFileSync(entryFile, '');
111
-
112
- const m = new Module(entryFile, defaultRules, defaultResolve);
113
- const result = m.require('./icon.png');
114
-
115
- expect(result).toBe(ASSET_TAG_OPEN + pngFile + ASSET_TAG_CLOSE);
116
- });
117
-
118
- it('does not wrap .json requires with asset tags', () => {
119
- tmpDir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'griffel-module-test-')));
120
-
121
- const jsonFile = path.join(tmpDir, 'data.json');
122
- fs.writeFileSync(jsonFile, '{"key": "value"}');
123
-
124
- const entryFile = path.join(tmpDir, 'entry.js');
125
- fs.writeFileSync(entryFile, '');
126
-
127
- const m = new Module(entryFile, defaultRules, defaultResolve);
128
- const result = m.require('./data.json');
129
-
130
- expect(result).toEqual({ key: 'value' });
131
- });
132
- });
133
- });
@@ -1,49 +0,0 @@
1
- import type { Node, Program } from 'oxc-parser';
2
-
3
- // Types from @linaria/babel-preset, internalized to remove the dependency
4
-
5
- export type EvaluatorResult = {
6
- code: string;
7
- imports: Map<string, string[]> | null;
8
- moduleKind: 'esm' | 'cjs';
9
- };
10
-
11
- export type EvalRule = {
12
- test?: RegExp | ((path: string) => boolean);
13
- action: Evaluator | 'ignore';
14
- };
15
-
16
- export type Evaluator = (
17
- filename: string,
18
- text: string,
19
- only: string[] | null,
20
- ) => EvaluatorResult;
21
-
22
- // Griffel-specific types
23
-
24
- export interface TransformPerfIssue {
25
- type: 'cjs-module' | 'barrel-export-star';
26
- /** The dependency file that caused the issue */
27
- dependencyFilename: string;
28
- }
29
-
30
- export interface EvaluationResult {
31
- confident: boolean;
32
- value?: unknown;
33
- error?: Error;
34
- }
35
-
36
- export interface AstEvaluatorContext {
37
- /** Full program AST */
38
- programAst: Program;
39
- /** Recursive evaluator callback (goes through base + all plugins) */
40
- evaluateNode: (node: Node) => unknown;
41
- }
42
-
43
- export interface AstEvaluatorPlugin {
44
- name: string;
45
- /**
46
- * Evaluate an AST node. Return DEOPT symbol to signal "can't handle this".
47
- */
48
- evaluateNode: (node: Node, context: AstEvaluatorContext) => unknown;
49
- }
@@ -1,45 +0,0 @@
1
- import { Module } from './module.mjs';
2
- import type { TransformResolver } from './module.mjs';
3
- import type { EvalRule, EvaluationResult } from './types.mjs';
4
-
5
- function isError(e: unknown): e is Error {
6
- return Object.prototype.toString.call(e) === '[object Error]';
7
- }
8
-
9
- export function vmEvaluator(
10
- sourceCode: string,
11
- filename: string,
12
- expressionCode: string,
13
- evaluationRules: EvalRule[],
14
- resolveFilename: TransformResolver,
15
- ): EvaluationResult {
16
- // Create a simple wrapper program for evaluation
17
- const codeForEvaluation = `
18
- ${sourceCode}
19
-
20
- export const __mkPreval = (() => {
21
- try {
22
- return ([${expressionCode}]);
23
- } catch (e) {
24
- return e;
25
- }
26
- })();
27
- `;
28
-
29
- try {
30
- const mod = new Module(filename, evaluationRules, resolveFilename);
31
- // useEvalCache=false: each source file produces unique codeForEvaluation (different sourceCode +
32
- // expressionCode), so the eval cache would never hit — skip the unnecessary hashing and map storage.
33
- mod.evaluate(codeForEvaluation, ['__mkPreval'], /* useEvalCache */ false);
34
-
35
- const result = (mod.exports as { __mkPreval: unknown }).__mkPreval;
36
-
37
- if (isError(result)) {
38
- return { confident: false, error: result };
39
- }
40
-
41
- return { confident: true, value: result };
42
- } catch (err) {
43
- return { confident: false, error: err as Error };
44
- }
45
- }
@@ -1,30 +0,0 @@
1
- import NativeModule from 'node:module';
2
- import { describe, expect, it } from 'vitest';
3
- import shakerEvaluator from '@griffel/transform-shaker';
4
- import { vmEvaluator } from './vmEvaluator.mjs';
5
- import type { TransformResolver } from './module.mjs';
6
-
7
- const evaluationRules = [
8
- {
9
- test: /[/\\]node_modules[/\\]/,
10
- action: 'ignore' as const,
11
- },
12
- {
13
- action: shakerEvaluator,
14
- },
15
- ];
16
-
17
- const defaultResolve: TransformResolver = (id, opts) => ({
18
- path: (NativeModule as unknown as { _resolveFilename: (id: string, options: unknown) => string })._resolveFilename(id, opts),
19
- builtin: false,
20
- });
21
-
22
- describe('evaluateStyleExpression', () => {
23
- it('evaluates expressions with source code context', () => {
24
- const sourceCode = 'const color = "blue"; const size = 16;';
25
- const result = vmEvaluator(sourceCode, '/test.ts', '{ color, fontSize: size }', evaluationRules, defaultResolve);
26
-
27
- expect(result.confident).toBe(true);
28
- expect(result.value).toEqual([{ color: 'blue', fontSize: 16 }]);
29
- });
30
- });