@griffel/transform 1.2.1 → 2.0.0
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/CHANGELOG.md +15 -2
- package/evaluation/batchEvaluator.d.mts +3 -2
- package/evaluation/module.d.mts +12 -9
- package/evaluation/types.d.mts +12 -12
- package/evaluation/vmEvaluator.d.mts +3 -2
- package/index.d.mts +4 -4
- package/package.json +2 -2
- package/transform.js +236 -161
- package/transformSync.d.mts +11 -7
- package/utils/convertESMtoCJS.d.mts +6 -0
- package/evaluation/hybridEvaluator.d.mts +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# Change Log - @griffel/transform
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 11 Mar 2026 13:31:20 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 2.0.0
|
|
8
|
+
|
|
9
|
+
Wed, 11 Mar 2026 13:31:20 GMT
|
|
10
|
+
|
|
11
|
+
### Major changes
|
|
12
|
+
|
|
13
|
+
- BREAKING: Replace @linaria/shaker with @griffel/transform-shaker. Remove babelOptions from TransformOptions. Remove StrictOptions type. (olfedias@microsoft.com)
|
|
14
|
+
|
|
15
|
+
### Patches
|
|
16
|
+
|
|
17
|
+
- feat: add collectPerfIssues option to TransformOptions (olfedias@microsoft.com)
|
|
18
|
+
- fix: fix VM result index mapping in batchEvaluator (olfedias@microsoft.com)
|
|
19
|
+
|
|
7
20
|
## 1.2.1
|
|
8
21
|
|
|
9
|
-
Fri, 06 Mar 2026 15:
|
|
22
|
+
Fri, 06 Mar 2026 15:56:28 GMT
|
|
10
23
|
|
|
11
24
|
### Patches
|
|
12
25
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Program } from 'oxc-parser';
|
|
2
|
-
import { StrictOptions, AstEvaluatorPlugin } from './types.mjs';
|
|
3
2
|
import { StyleCall } from '../types.mjs';
|
|
3
|
+
import { TransformResolver } from './module.mjs';
|
|
4
|
+
import { AstEvaluatorPlugin, EvalRule } from './types.mjs';
|
|
4
5
|
/**
|
|
5
6
|
* Batch evaluates all style calls in a file for better performance.
|
|
6
7
|
* Uses static evaluation first, then falls back to VM evaluation for complex expressions.
|
|
7
8
|
* Optimizes VM evaluation by sharing module loading and parsing overhead.
|
|
8
9
|
*/
|
|
9
|
-
export declare function batchEvaluator(sourceCode: string, filename: string, styleCalls: StyleCall[],
|
|
10
|
+
export declare function batchEvaluator(sourceCode: string, filename: string, styleCalls: StyleCall[], evaluationRules: EvalRule[], resolveFilename: TransformResolver, programAst: Program, astEvaluationPlugins?: AstEvaluatorPlugin[]): {
|
|
10
11
|
usedVMForEvaluation: boolean;
|
|
11
12
|
evaluationResults: unknown[];
|
|
12
13
|
};
|
package/evaluation/module.d.mts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EvalRule } from './types.mjs';
|
|
2
|
+
export type TransformResolver = (id: string, options: {
|
|
3
|
+
filename: string;
|
|
4
|
+
paths: readonly string[];
|
|
5
|
+
}) => {
|
|
6
|
+
path: string;
|
|
7
|
+
builtin: boolean;
|
|
8
|
+
};
|
|
2
9
|
export declare class Module {
|
|
3
10
|
readonly id: string;
|
|
4
11
|
readonly filename: string;
|
|
5
12
|
readonly paths: readonly string[];
|
|
6
|
-
|
|
13
|
+
rules: EvalRule[];
|
|
7
14
|
imports: Map<string, string[]> | null;
|
|
8
15
|
dependencies: string[] | null;
|
|
9
16
|
transform: ((code: string, filename: string) => string) | null;
|
|
17
|
+
static readonly extensions: Set<string>;
|
|
10
18
|
exports: unknown;
|
|
11
|
-
|
|
19
|
+
private readonly resolveFilename;
|
|
12
20
|
private debug;
|
|
13
21
|
private debuggerDepth;
|
|
14
|
-
constructor(filename: string,
|
|
15
|
-
resolve: (id: string) => string;
|
|
22
|
+
constructor(filename: string, rules: EvalRule[], resolveFilename: TransformResolver, debuggerDepth?: number);
|
|
16
23
|
require: ((id: string) => unknown) & {
|
|
17
24
|
ensure: () => void;
|
|
18
25
|
cache: Record<string, Module>;
|
|
@@ -21,9 +28,5 @@ export declare class Module {
|
|
|
21
28
|
evaluate(text: string, only?: string[] | null): void;
|
|
22
29
|
static invalidate: () => void;
|
|
23
30
|
static invalidateEvalCache: () => void;
|
|
24
|
-
static _resolveFilename: (id: string, options: {
|
|
25
|
-
filename: string;
|
|
26
|
-
paths: readonly string[];
|
|
27
|
-
}) => string;
|
|
28
31
|
static _nodeModulePaths: (filename: string) => string[];
|
|
29
32
|
}
|
package/evaluation/types.d.mts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Node, Program } from 'oxc-parser';
|
|
2
|
-
export type
|
|
2
|
+
export type EvaluatorResult = {
|
|
3
|
+
code: string;
|
|
4
|
+
imports: Map<string, string[]> | null;
|
|
5
|
+
moduleKind: 'esm' | 'cjs';
|
|
6
|
+
};
|
|
3
7
|
export type EvalRule = {
|
|
4
8
|
test?: RegExp | ((path: string) => boolean);
|
|
5
|
-
action: Evaluator | 'ignore'
|
|
6
|
-
};
|
|
7
|
-
export type StrictOptions = {
|
|
8
|
-
displayName: boolean;
|
|
9
|
-
evaluate: boolean;
|
|
10
|
-
babelOptions: {
|
|
11
|
-
plugins?: unknown[];
|
|
12
|
-
presets?: unknown[];
|
|
13
|
-
[key: string]: unknown;
|
|
14
|
-
};
|
|
15
|
-
rules: EvalRule[];
|
|
9
|
+
action: Evaluator | 'ignore';
|
|
16
10
|
};
|
|
11
|
+
export type Evaluator = (filename: string, text: string, only: string[] | null) => EvaluatorResult;
|
|
12
|
+
export interface TransformPerfIssue {
|
|
13
|
+
type: 'cjs-module' | 'barrel-export-star';
|
|
14
|
+
/** The dependency file that caused the issue */
|
|
15
|
+
dependencyFilename: string;
|
|
16
|
+
}
|
|
17
17
|
export interface EvaluationResult {
|
|
18
18
|
confident: boolean;
|
|
19
19
|
value?: unknown;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { TransformResolver } from './module.mjs';
|
|
2
|
+
import { EvalRule, EvaluationResult } from './types.mjs';
|
|
3
|
+
export declare function vmEvaluator(sourceCode: string, filename: string, expressionCode: string, evaluationRules: EvalRule[], resolveFilename: TransformResolver): EvaluationResult;
|
package/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { default as shakerEvaluator } from '@
|
|
2
|
-
export { Module } from './evaluation/module.mjs';
|
|
1
|
+
export { default as shakerEvaluator } from '@griffel/transform-shaker';
|
|
2
|
+
export { Module, type TransformResolver } from './evaluation/module.mjs';
|
|
3
3
|
export * as EvalCache from './evaluation/evalCache.mjs';
|
|
4
4
|
export { ASSET_TAG_OPEN, ASSET_TAG_CLOSE } from './constants.mjs';
|
|
5
|
-
export type { Evaluator, EvalRule } from './evaluation/types.mjs';
|
|
5
|
+
export type { Evaluator, EvaluatorResult, EvalRule } from './evaluation/types.mjs';
|
|
6
6
|
export { transformSync, type TransformOptions, type TransformResult } from './transformSync.mjs';
|
|
7
7
|
export { DEOPT, type Deopt } from './evaluation/astEvaluator.mjs';
|
|
8
|
-
export type { AstEvaluatorPlugin, AstEvaluatorContext } from './evaluation/types.mjs';
|
|
8
|
+
export type { AstEvaluatorPlugin, AstEvaluatorContext, TransformPerfIssue } from './evaluation/types.mjs';
|
|
9
9
|
export { fluentTokensPlugin } from './evaluation/fluentTokensPlugin.mjs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griffel/transform",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A package that performs build time transforms for Griffel",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@griffel/core": "^1.20.1",
|
|
20
|
-
"@
|
|
20
|
+
"@griffel/transform-shaker": "^1.0.0",
|
|
21
21
|
"debug": "^4.3.0",
|
|
22
22
|
"magic-string": "^0.30.19",
|
|
23
23
|
"oxc-parser": "^0.116.0",
|
package/transform.js
CHANGED
|
@@ -1,17 +1,181 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { default as default2 } from "@
|
|
1
|
+
import shakerEvaluator from "@griffel/transform-shaker";
|
|
2
|
+
import { default as default2 } from "@griffel/transform-shaker";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import NativeModule from "node:module";
|
|
5
|
-
import path
|
|
5
|
+
import path from "node:path";
|
|
6
6
|
import vm from "node:vm";
|
|
7
7
|
import createDebug from "debug";
|
|
8
|
+
import { parseSync } from "oxc-parser";
|
|
9
|
+
import MagicString from "magic-string";
|
|
8
10
|
import { createHash } from "node:crypto";
|
|
9
|
-
import { rawTransferSupported, parseSync } from "oxc-parser";
|
|
10
11
|
import { ScopeTracker, walk } from "oxc-walker";
|
|
11
|
-
import MagicString from "magic-string";
|
|
12
12
|
import { resolveStaticStyleRules, resolveResetStyleRules, resolveStyleRulesForSlots, normalizeCSSBucketEntry } from "@griffel/core";
|
|
13
13
|
const ASSET_TAG_OPEN = "<griffel-asset>";
|
|
14
14
|
const ASSET_TAG_CLOSE = "</griffel-asset>";
|
|
15
|
+
const prop = (node, key) => node[key];
|
|
16
|
+
function extractDeclaredNames(node) {
|
|
17
|
+
switch (node.type) {
|
|
18
|
+
case "Identifier":
|
|
19
|
+
return [prop(node, "name")];
|
|
20
|
+
case "ObjectPattern":
|
|
21
|
+
return prop(node, "properties").flatMap((p) => {
|
|
22
|
+
if (p.type === "RestElement") {
|
|
23
|
+
return extractDeclaredNames(prop(p, "argument"));
|
|
24
|
+
}
|
|
25
|
+
return extractDeclaredNames(prop(p, "value"));
|
|
26
|
+
});
|
|
27
|
+
case "ArrayPattern":
|
|
28
|
+
return prop(node, "elements").filter(Boolean).flatMap((el) => extractDeclaredNames(el));
|
|
29
|
+
case "AssignmentPattern":
|
|
30
|
+
return extractDeclaredNames(prop(node, "left"));
|
|
31
|
+
default:
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function convertESMtoCJS(code, filename) {
|
|
36
|
+
const parseResult = parseSync(filename, code);
|
|
37
|
+
if (parseResult.errors.length > 0) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`convertESMtoCJS: failed to parse "${filename}": ${parseResult.errors.map((e) => e.message).join(", ")}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const program = parseResult.program;
|
|
43
|
+
let hasESM = false;
|
|
44
|
+
for (const node of program.body) {
|
|
45
|
+
if (node.type === "ImportDeclaration" || node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ExportAllDeclaration") {
|
|
46
|
+
hasESM = true;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!hasESM) {
|
|
51
|
+
return code;
|
|
52
|
+
}
|
|
53
|
+
const ms = new MagicString(code);
|
|
54
|
+
for (const node of program.body) {
|
|
55
|
+
switch (node.type) {
|
|
56
|
+
case "ImportDeclaration": {
|
|
57
|
+
const source = prop(prop(node, "source"), "value");
|
|
58
|
+
const specifiers = prop(node, "specifiers");
|
|
59
|
+
if (specifiers.length === 0) {
|
|
60
|
+
ms.overwrite(node.start, node.end, `require(${JSON.stringify(source)});`);
|
|
61
|
+
} else {
|
|
62
|
+
let defaultName = null;
|
|
63
|
+
let namespaceName = null;
|
|
64
|
+
const namedImports = [];
|
|
65
|
+
for (const spec of specifiers) {
|
|
66
|
+
if (spec.type === "ImportDefaultSpecifier") {
|
|
67
|
+
defaultName = prop(prop(spec, "local"), "name");
|
|
68
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
69
|
+
namespaceName = prop(prop(spec, "local"), "name");
|
|
70
|
+
} else if (spec.type === "ImportSpecifier") {
|
|
71
|
+
const importedNode = prop(spec, "imported");
|
|
72
|
+
const imported = importedNode.type === "Identifier" ? prop(importedNode, "name") : prop(importedNode, "value");
|
|
73
|
+
const local = prop(prop(spec, "local"), "name");
|
|
74
|
+
if (imported === local) {
|
|
75
|
+
namedImports.push(imported);
|
|
76
|
+
} else {
|
|
77
|
+
namedImports.push(`${imported}: ${local}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const parts = [];
|
|
82
|
+
if (namespaceName) {
|
|
83
|
+
parts.push(`const ${namespaceName} = require(${JSON.stringify(source)});`);
|
|
84
|
+
} else if (defaultName && namedImports.length > 0) {
|
|
85
|
+
const tempVar = `_require$${defaultName}`;
|
|
86
|
+
parts.push(`const ${tempVar} = require(${JSON.stringify(source)});`);
|
|
87
|
+
parts.push(`const ${defaultName} = ${tempVar}.__esModule ? ${tempVar}.default : ${tempVar};`);
|
|
88
|
+
parts.push(`const { ${namedImports.join(", ")} } = ${tempVar};`);
|
|
89
|
+
} else if (defaultName) {
|
|
90
|
+
const tempVar = `_require$${defaultName}`;
|
|
91
|
+
parts.push(`const ${tempVar} = require(${JSON.stringify(source)});`);
|
|
92
|
+
parts.push(`const ${defaultName} = ${tempVar}.__esModule ? ${tempVar}.default : ${tempVar};`);
|
|
93
|
+
} else if (namedImports.length > 0) {
|
|
94
|
+
parts.push(`const { ${namedImports.join(", ")} } = require(${JSON.stringify(source)});`);
|
|
95
|
+
}
|
|
96
|
+
ms.overwrite(node.start, node.end, parts.join("\n"));
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case "ExportNamedDeclaration": {
|
|
101
|
+
const decl = prop(node, "declaration");
|
|
102
|
+
if (decl) {
|
|
103
|
+
ms.overwrite(node.start, decl.start, "");
|
|
104
|
+
if (decl.type === "VariableDeclaration") {
|
|
105
|
+
const names = prop(decl, "declarations").flatMap(
|
|
106
|
+
(d) => extractDeclaredNames(prop(d, "id"))
|
|
107
|
+
);
|
|
108
|
+
const exportsCode = names.map((name) => `exports.${name} = ${name};`).join(" ");
|
|
109
|
+
ms.appendLeft(node.end, "\n" + exportsCode);
|
|
110
|
+
} else if (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration") {
|
|
111
|
+
const id = prop(decl, "id");
|
|
112
|
+
if (id) {
|
|
113
|
+
const name = prop(id, "name");
|
|
114
|
+
ms.appendLeft(node.end, `
|
|
115
|
+
exports.${name} = ${name};`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} else if (prop(node, "source")) {
|
|
119
|
+
const source = prop(prop(node, "source"), "value");
|
|
120
|
+
const parts = [];
|
|
121
|
+
for (const spec of prop(node, "specifiers")) {
|
|
122
|
+
const localNode = prop(spec, "local");
|
|
123
|
+
const exportedNode = prop(spec, "exported");
|
|
124
|
+
const local = localNode.type === "Identifier" ? prop(localNode, "name") : prop(localNode, "value");
|
|
125
|
+
const exported = exportedNode.type === "Identifier" ? prop(exportedNode, "name") : prop(exportedNode, "value");
|
|
126
|
+
parts.push(
|
|
127
|
+
`exports[${JSON.stringify(exported)}] = require(${JSON.stringify(source)})[${JSON.stringify(local)}];`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
ms.overwrite(node.start, node.end, parts.join("\n"));
|
|
131
|
+
} else {
|
|
132
|
+
const parts = [];
|
|
133
|
+
for (const spec of prop(node, "specifiers")) {
|
|
134
|
+
const localNode = prop(spec, "local");
|
|
135
|
+
const exportedNode = prop(spec, "exported");
|
|
136
|
+
const local = localNode.type === "Identifier" ? prop(localNode, "name") : prop(localNode, "value");
|
|
137
|
+
const exported = exportedNode.type === "Identifier" ? prop(exportedNode, "name") : prop(exportedNode, "value");
|
|
138
|
+
parts.push(`exports[${JSON.stringify(exported)}] = ${local};`);
|
|
139
|
+
}
|
|
140
|
+
ms.overwrite(node.start, node.end, parts.join("\n"));
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case "ExportDefaultDeclaration": {
|
|
145
|
+
const decl = prop(node, "declaration");
|
|
146
|
+
if (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration") {
|
|
147
|
+
const id = prop(decl, "id");
|
|
148
|
+
if (id) {
|
|
149
|
+
ms.overwrite(node.start, decl.start, "");
|
|
150
|
+
ms.appendLeft(node.end, `
|
|
151
|
+
exports.default = ${prop(id, "name")};`);
|
|
152
|
+
} else {
|
|
153
|
+
ms.overwrite(node.start, decl.start, "exports.default = ");
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
ms.overwrite(node.start, decl.start, "exports.default = ");
|
|
157
|
+
if (code[node.end - 1] !== ";") {
|
|
158
|
+
ms.appendLeft(node.end, ";");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case "ExportAllDeclaration": {
|
|
164
|
+
const source = prop(prop(node, "source"), "value");
|
|
165
|
+
const exportedNode = prop(node, "exported");
|
|
166
|
+
if (exportedNode) {
|
|
167
|
+
const name = exportedNode.type === "Identifier" ? prop(exportedNode, "name") : prop(exportedNode, "value");
|
|
168
|
+
ms.overwrite(node.start, node.end, `exports[${JSON.stringify(name)}] = require(${JSON.stringify(source)});`);
|
|
169
|
+
} else {
|
|
170
|
+
ms.overwrite(node.start, node.end, `Object.assign(exports, require(${JSON.stringify(source)}));`);
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
ms.prepend('Object.defineProperty(exports, "__esModule", { value: true });\n');
|
|
177
|
+
return ms.toString();
|
|
178
|
+
}
|
|
15
179
|
const debug$1 = createDebug("griffel:eval-cache");
|
|
16
180
|
const fileHashes = /* @__PURE__ */ new Map();
|
|
17
181
|
const evalCache = /* @__PURE__ */ new Map();
|
|
@@ -126,41 +290,6 @@ const mockProcess = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
126
290
|
uvCounters
|
|
127
291
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
128
292
|
const debug = createDebug("griffel:module");
|
|
129
|
-
const builtins = {
|
|
130
|
-
assert: true,
|
|
131
|
-
buffer: true,
|
|
132
|
-
child_process: false,
|
|
133
|
-
cluster: false,
|
|
134
|
-
console: true,
|
|
135
|
-
constants: true,
|
|
136
|
-
crypto: true,
|
|
137
|
-
dgram: false,
|
|
138
|
-
dns: false,
|
|
139
|
-
domain: true,
|
|
140
|
-
events: true,
|
|
141
|
-
fs: false,
|
|
142
|
-
http: true,
|
|
143
|
-
https: true,
|
|
144
|
-
module: false,
|
|
145
|
-
net: false,
|
|
146
|
-
os: true,
|
|
147
|
-
path: true,
|
|
148
|
-
punycode: true,
|
|
149
|
-
process: true,
|
|
150
|
-
querystring: true,
|
|
151
|
-
readline: false,
|
|
152
|
-
repl: false,
|
|
153
|
-
stream: true,
|
|
154
|
-
string_decoder: true,
|
|
155
|
-
sys: true,
|
|
156
|
-
timers: true,
|
|
157
|
-
tls: false,
|
|
158
|
-
tty: true,
|
|
159
|
-
url: true,
|
|
160
|
-
util: true,
|
|
161
|
-
vm: true,
|
|
162
|
-
zlib: true
|
|
163
|
-
};
|
|
164
293
|
let cache = {};
|
|
165
294
|
const NOOP = () => {
|
|
166
295
|
};
|
|
@@ -171,18 +300,20 @@ const createCustomDebug = (depth) => (namespaces, arg1, ...args) => {
|
|
|
171
300
|
class Module {
|
|
172
301
|
id;
|
|
173
302
|
filename;
|
|
174
|
-
|
|
303
|
+
rules;
|
|
175
304
|
imports = null;
|
|
176
305
|
dependencies = null;
|
|
177
306
|
transform = null;
|
|
307
|
+
static extensions = /* @__PURE__ */ new Set([".json", ".js", ".jsx", ".ts", ".tsx", ".cjs", ".mjs", ".mts", ".cts"]);
|
|
178
308
|
exports = {};
|
|
179
|
-
|
|
309
|
+
resolveFilename;
|
|
180
310
|
debug;
|
|
181
311
|
debuggerDepth;
|
|
182
|
-
constructor(filename,
|
|
312
|
+
constructor(filename, rules, resolveFilename, debuggerDepth = 0) {
|
|
183
313
|
this.id = filename;
|
|
184
314
|
this.filename = filename;
|
|
185
|
-
this.
|
|
315
|
+
this.rules = rules;
|
|
316
|
+
this.resolveFilename = resolveFilename;
|
|
186
317
|
this.debuggerDepth = debuggerDepth;
|
|
187
318
|
this.debug = createCustomDebug(debuggerDepth);
|
|
188
319
|
Object.defineProperties(this, {
|
|
@@ -204,38 +335,16 @@ class Module {
|
|
|
204
335
|
}
|
|
205
336
|
});
|
|
206
337
|
this.exports = {};
|
|
207
|
-
this.extensions = [".json", ".js", ".jsx", ".ts", ".tsx", ".cjs"];
|
|
208
338
|
this.debug("prepare", filename);
|
|
209
339
|
}
|
|
210
|
-
resolve = (id) => {
|
|
211
|
-
const extensions = NativeModule._extensions;
|
|
212
|
-
const added = [];
|
|
213
|
-
try {
|
|
214
|
-
this.extensions.forEach((ext) => {
|
|
215
|
-
if (ext in extensions) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
extensions[ext] = NOOP;
|
|
219
|
-
added.push(ext);
|
|
220
|
-
});
|
|
221
|
-
return Module._resolveFilename(id, this);
|
|
222
|
-
} finally {
|
|
223
|
-
added.forEach((ext) => delete extensions[ext]);
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
340
|
require = Object.assign(
|
|
227
341
|
(id) => {
|
|
228
342
|
this.debug("require", id);
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return require(id);
|
|
232
|
-
}
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
const filename = this.resolve(id);
|
|
236
|
-
if (filename === id && !path.isAbsolute(id)) {
|
|
343
|
+
const resolved = this.resolveFilename(id, this);
|
|
344
|
+
if (resolved.builtin) {
|
|
237
345
|
throw new Error(`Unable to import "${id}". Importing Node builtins is not supported in the sandbox.`);
|
|
238
346
|
}
|
|
347
|
+
const filename = resolved.path;
|
|
239
348
|
this.dependencies?.push(id);
|
|
240
349
|
let cacheKey = filename;
|
|
241
350
|
let only = [];
|
|
@@ -249,12 +358,13 @@ class Module {
|
|
|
249
358
|
let m = cache[cacheKey];
|
|
250
359
|
if (!m) {
|
|
251
360
|
this.debug("cached:not-exist", id);
|
|
252
|
-
m = new Module(filename, this.
|
|
361
|
+
m = new Module(filename, this.rules, this.resolveFilename, this.debuggerDepth + 1);
|
|
253
362
|
m.transform = this.transform;
|
|
254
363
|
cache[cacheKey] = m;
|
|
255
|
-
|
|
364
|
+
const ext = path.extname(filename).toLowerCase();
|
|
365
|
+
if (Module.extensions.has(ext)) {
|
|
256
366
|
const code = fs.readFileSync(filename, "utf-8");
|
|
257
|
-
if (
|
|
367
|
+
if (ext === ".json") {
|
|
258
368
|
m.exports = JSON.parse(code);
|
|
259
369
|
} else {
|
|
260
370
|
m.evaluate(code, only.includes("*") ? ["*"] : only);
|
|
@@ -270,16 +380,16 @@ class Module {
|
|
|
270
380
|
{
|
|
271
381
|
ensure: NOOP,
|
|
272
382
|
cache,
|
|
273
|
-
resolve: this.
|
|
383
|
+
resolve: (id) => this.resolveFilename(id, this).path
|
|
274
384
|
}
|
|
275
385
|
);
|
|
276
386
|
evaluate(text, only = null) {
|
|
277
387
|
const { filename } = this;
|
|
278
388
|
let action = "ignore";
|
|
279
|
-
for (let i = this.
|
|
280
|
-
const { test } = this.
|
|
281
|
-
if (!test || (typeof test === "function" ? test(filename) : test
|
|
282
|
-
action = this.
|
|
389
|
+
for (let i = this.rules.length - 1; i >= 0; i--) {
|
|
390
|
+
const { test } = this.rules[i];
|
|
391
|
+
if (!test || (typeof test === "function" ? test(filename) : test.test(filename))) {
|
|
392
|
+
action = this.rules[i].action;
|
|
283
393
|
break;
|
|
284
394
|
}
|
|
285
395
|
}
|
|
@@ -293,13 +403,13 @@ class Module {
|
|
|
293
403
|
this.debug("ignore", `${filename}`);
|
|
294
404
|
code = text;
|
|
295
405
|
} else {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
406
|
+
this.debug("prepare-evaluation", this.filename, "using", action.name);
|
|
407
|
+
const result = action(this.filename, text, only);
|
|
408
|
+
code = result.code;
|
|
409
|
+
this.imports = result.imports;
|
|
410
|
+
if (result.moduleKind === "esm") {
|
|
411
|
+
code = convertESMtoCJS(code, this.filename);
|
|
412
|
+
}
|
|
303
413
|
this.debug("evaluate", `${this.filename} (only ${(only || []).join(", ")}):
|
|
304
414
|
${code}`);
|
|
305
415
|
}
|
|
@@ -315,6 +425,7 @@ ${code}`);
|
|
|
315
425
|
setImmediate: NOOP,
|
|
316
426
|
setInterval: NOOP,
|
|
317
427
|
setTimeout: NOOP,
|
|
428
|
+
fetch: NOOP,
|
|
318
429
|
global,
|
|
319
430
|
process: mockProcess,
|
|
320
431
|
module: this,
|
|
@@ -332,13 +443,6 @@ ${code}`);
|
|
|
332
443
|
static invalidateEvalCache = () => {
|
|
333
444
|
clear();
|
|
334
445
|
};
|
|
335
|
-
// Alias to resolve the module using node's resolve algorithm
|
|
336
|
-
// This static property can be overridden by the webpack loader
|
|
337
|
-
// This allows us to use webpack's module resolution algorithm
|
|
338
|
-
static _resolveFilename = (id, options) => NativeModule._resolveFilename(
|
|
339
|
-
id,
|
|
340
|
-
options
|
|
341
|
-
);
|
|
342
446
|
static _nodeModulePaths = (filename) => NativeModule._nodeModulePaths(filename);
|
|
343
447
|
}
|
|
344
448
|
const DEOPT = /* @__PURE__ */ Symbol("deopt");
|
|
@@ -369,17 +473,17 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
369
473
|
}
|
|
370
474
|
function evaluateObjectExpression(node2) {
|
|
371
475
|
const obj = {};
|
|
372
|
-
for (const
|
|
373
|
-
if (
|
|
476
|
+
for (const prop2 of node2.properties) {
|
|
477
|
+
if (prop2.type !== "Property" || prop2.kind !== "init") {
|
|
374
478
|
return DEOPT;
|
|
375
479
|
}
|
|
376
480
|
let key;
|
|
377
|
-
if (
|
|
481
|
+
if (prop2.computed) {
|
|
378
482
|
return DEOPT;
|
|
379
|
-
} else if (
|
|
380
|
-
key =
|
|
381
|
-
} else if (
|
|
382
|
-
const keyLiteral =
|
|
483
|
+
} else if (prop2.key.type === "Identifier") {
|
|
484
|
+
key = prop2.key.name;
|
|
485
|
+
} else if (prop2.key.type === "Literal") {
|
|
486
|
+
const keyLiteral = prop2.key;
|
|
383
487
|
if (typeof keyLiteral.value === "string" || typeof keyLiteral.value === "number") {
|
|
384
488
|
key = String(keyLiteral.value);
|
|
385
489
|
} else {
|
|
@@ -388,7 +492,7 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
388
492
|
} else {
|
|
389
493
|
return DEOPT;
|
|
390
494
|
}
|
|
391
|
-
const value = evaluateNode(
|
|
495
|
+
const value = evaluateNode(prop2.value);
|
|
392
496
|
if (value === DEOPT) {
|
|
393
497
|
return DEOPT;
|
|
394
498
|
}
|
|
@@ -411,34 +515,20 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
411
515
|
function isError(e) {
|
|
412
516
|
return Object.prototype.toString.call(e) === "[object Error]";
|
|
413
517
|
}
|
|
414
|
-
function vmEvaluator(sourceCode, filename, expressionCode,
|
|
518
|
+
function vmEvaluator(sourceCode, filename, expressionCode, evaluationRules, resolveFilename) {
|
|
415
519
|
const codeForEvaluation = `
|
|
416
520
|
${sourceCode}
|
|
417
521
|
|
|
418
|
-
const __mkPreval = (() => {
|
|
522
|
+
export const __mkPreval = (() => {
|
|
419
523
|
try {
|
|
420
524
|
return ([${expressionCode}]);
|
|
421
525
|
} catch (e) {
|
|
422
526
|
return e;
|
|
423
527
|
}
|
|
424
528
|
})();
|
|
425
|
-
|
|
426
|
-
if (typeof module !== 'undefined' && module.exports) {
|
|
427
|
-
module.exports = { __mkPreval };
|
|
428
|
-
}
|
|
429
529
|
`;
|
|
430
530
|
try {
|
|
431
|
-
const
|
|
432
|
-
displayName: false,
|
|
433
|
-
evaluate: true,
|
|
434
|
-
rules: evaluationRules,
|
|
435
|
-
babelOptions: {
|
|
436
|
-
...babelOptions,
|
|
437
|
-
configFile: false,
|
|
438
|
-
babelrc: false
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
const mod = new Module(filename, options);
|
|
531
|
+
const mod = new Module(filename, evaluationRules, resolveFilename);
|
|
442
532
|
mod.evaluate(codeForEvaluation, ["__mkPreval"]);
|
|
443
533
|
const result = mod.exports.__mkPreval;
|
|
444
534
|
if (isError(result)) {
|
|
@@ -449,10 +539,10 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
449
539
|
return { confident: false, error: err };
|
|
450
540
|
}
|
|
451
541
|
}
|
|
452
|
-
function batchEvaluator(sourceCode, filename, styleCalls,
|
|
542
|
+
function batchEvaluator(sourceCode, filename, styleCalls, evaluationRules, resolveFilename, programAst, astEvaluationPlugins = []) {
|
|
453
543
|
const evaluationResults = new Array(styleCalls.length);
|
|
454
|
-
const
|
|
455
|
-
let
|
|
544
|
+
const vmIndices = [];
|
|
545
|
+
let expressionCode = "";
|
|
456
546
|
for (let i = 0; i < styleCalls.length; i++) {
|
|
457
547
|
const styleCall = styleCalls[i];
|
|
458
548
|
const staticResult = astEvaluator(styleCall.argumentNode, programAst, astEvaluationPlugins);
|
|
@@ -460,16 +550,19 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
|
|
|
460
550
|
evaluationResults[i] = staticResult.value;
|
|
461
551
|
continue;
|
|
462
552
|
}
|
|
463
|
-
|
|
464
|
-
|
|
553
|
+
if (expressionCode.length > 0) {
|
|
554
|
+
expressionCode += ",";
|
|
555
|
+
}
|
|
556
|
+
expressionCode += styleCall.argumentCode;
|
|
557
|
+
vmIndices.push(i);
|
|
465
558
|
}
|
|
466
|
-
if (
|
|
559
|
+
if (vmIndices.length === 0) {
|
|
467
560
|
return {
|
|
468
561
|
usedVMForEvaluation: false,
|
|
469
562
|
evaluationResults
|
|
470
563
|
};
|
|
471
564
|
}
|
|
472
|
-
const vmResult = vmEvaluator(sourceCode, filename,
|
|
565
|
+
const vmResult = vmEvaluator(sourceCode, filename, expressionCode, evaluationRules, resolveFilename);
|
|
473
566
|
if (!vmResult.confident) {
|
|
474
567
|
if (vmResult.error) {
|
|
475
568
|
throw vmResult.error;
|
|
@@ -478,45 +571,14 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
|
|
|
478
571
|
}
|
|
479
572
|
}
|
|
480
573
|
const vmValues = vmResult.value;
|
|
481
|
-
for (let i = 0; i <
|
|
482
|
-
|
|
483
|
-
continue;
|
|
484
|
-
}
|
|
485
|
-
evaluationResults[i] = vmValues[i];
|
|
574
|
+
for (let i = 0; i < vmIndices.length; i++) {
|
|
575
|
+
evaluationResults[vmIndices[i]] = vmValues[i];
|
|
486
576
|
}
|
|
487
577
|
return {
|
|
488
578
|
usedVMForEvaluation: true,
|
|
489
579
|
evaluationResults
|
|
490
580
|
};
|
|
491
581
|
}
|
|
492
|
-
const CJS_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".json"]);
|
|
493
|
-
const ESM_EXTENSIONS = /* @__PURE__ */ new Set([".mjs", ".mts"]);
|
|
494
|
-
const useRawTransfer = rawTransferSupported();
|
|
495
|
-
const NODE_MODULES_RE = /[/\\]node_modules[/\\]/;
|
|
496
|
-
function createHybridEvaluator(shakerEvaluator2) {
|
|
497
|
-
return (filename, options, text, only) => {
|
|
498
|
-
if (!NODE_MODULES_RE.test(filename)) {
|
|
499
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
500
|
-
}
|
|
501
|
-
const ext = extname(filename);
|
|
502
|
-
if (CJS_EXTENSIONS.has(ext)) {
|
|
503
|
-
return [text, null];
|
|
504
|
-
}
|
|
505
|
-
if (ESM_EXTENSIONS.has(ext)) {
|
|
506
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
507
|
-
}
|
|
508
|
-
const parseResult = parseSync(filename, text, {
|
|
509
|
-
sourceType: "unambiguous",
|
|
510
|
-
...useRawTransfer && { experimentalLazy: true }
|
|
511
|
-
});
|
|
512
|
-
const isESM = parseResult.module.hasModuleSyntax;
|
|
513
|
-
parseResult.dispose?.();
|
|
514
|
-
if (!isESM) {
|
|
515
|
-
return [text, null];
|
|
516
|
-
}
|
|
517
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
518
|
-
};
|
|
519
|
-
}
|
|
520
582
|
function evaluateTemplateLiteralWithTokens(node) {
|
|
521
583
|
let result = "";
|
|
522
584
|
for (let i = 0; i < node.quasis.length; i++) {
|
|
@@ -568,7 +630,18 @@ function dedupeCSSRules(cssRulesByBucket) {
|
|
|
568
630
|
})
|
|
569
631
|
);
|
|
570
632
|
}
|
|
571
|
-
const
|
|
633
|
+
const EXPORT_STAR_RE = /export\s+\*\s+from\s/;
|
|
634
|
+
function wrapWithPerfIssues(evaluator, perfIssues) {
|
|
635
|
+
return (filename, text, only) => {
|
|
636
|
+
const result = evaluator(filename, text, only);
|
|
637
|
+
if (result.moduleKind === "cjs") {
|
|
638
|
+
perfIssues.push({ type: "cjs-module", dependencyFilename: filename });
|
|
639
|
+
} else if (EXPORT_STAR_RE.test(result.code)) {
|
|
640
|
+
perfIssues.push({ type: "barrel-export-star", dependencyFilename: filename });
|
|
641
|
+
}
|
|
642
|
+
return result;
|
|
643
|
+
};
|
|
644
|
+
}
|
|
572
645
|
const RUNTIME_IDENTIFIERS = /* @__PURE__ */ new Map([
|
|
573
646
|
["makeStyles", "__css"],
|
|
574
647
|
["makeResetStyles", "__resetCSS"],
|
|
@@ -634,13 +707,14 @@ function concatCSSRulesByBucket(bucketA = {}, bucketB) {
|
|
|
634
707
|
return bucketA;
|
|
635
708
|
}
|
|
636
709
|
function transformSync(sourceCode, options) {
|
|
710
|
+
const perfIssues = options.collectPerfIssues ? [] : void 0;
|
|
637
711
|
const {
|
|
638
|
-
babelOptions = {},
|
|
639
712
|
filename,
|
|
713
|
+
resolveModule,
|
|
640
714
|
classNameHashSalt = "",
|
|
641
715
|
generateMetadata = false,
|
|
642
716
|
modules = ["@griffel/core", "@griffel/react", "@fluentui/react-components"],
|
|
643
|
-
evaluationRules = [{ action:
|
|
717
|
+
evaluationRules = [{ action: perfIssues ? wrapWithPerfIssues(shakerEvaluator, perfIssues) : shakerEvaluator }],
|
|
644
718
|
astEvaluationPlugins = [fluentTokensPlugin]
|
|
645
719
|
} = options;
|
|
646
720
|
if (!filename) {
|
|
@@ -740,8 +814,8 @@ function transformSync(sourceCode, options) {
|
|
|
740
814
|
sourceCode,
|
|
741
815
|
filename,
|
|
742
816
|
styleCalls,
|
|
743
|
-
babelOptions,
|
|
744
817
|
evaluationRules,
|
|
818
|
+
resolveModule,
|
|
745
819
|
programAst,
|
|
746
820
|
astEvaluationPlugins
|
|
747
821
|
);
|
|
@@ -804,7 +878,8 @@ function transformSync(sourceCode, options) {
|
|
|
804
878
|
code: magicString.toString(),
|
|
805
879
|
cssRulesByBucket,
|
|
806
880
|
usedProcessing: true,
|
|
807
|
-
usedVMForEvaluation
|
|
881
|
+
usedVMForEvaluation,
|
|
882
|
+
perfIssues
|
|
808
883
|
};
|
|
809
884
|
}
|
|
810
885
|
export {
|
package/transformSync.d.mts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TransformResolver } from './evaluation/module.mjs';
|
|
2
|
+
import { EvalRule, TransformPerfIssue, AstEvaluatorPlugin } from './evaluation/types.mjs';
|
|
2
3
|
import { CSSRulesByBucket } from '@griffel/core';
|
|
3
4
|
export type TransformOptions = {
|
|
4
5
|
filename: string;
|
|
6
|
+
/** Custom module resolver used to resolve imports inside evaluated modules. */
|
|
7
|
+
resolveModule: TransformResolver;
|
|
5
8
|
classNameHashSalt?: string;
|
|
6
9
|
/**
|
|
7
10
|
* Returns the evaluated CSS rules in the file result metadata
|
|
@@ -10,21 +13,22 @@ export type TransformOptions = {
|
|
|
10
13
|
generateMetadata?: boolean;
|
|
11
14
|
/** Defines set of modules and imports handled by a transformPlugin. */
|
|
12
15
|
modules?: string[];
|
|
13
|
-
/**
|
|
14
|
-
* If you need to specify custom Babel configuration, you can pass them here. These options will be used by the
|
|
15
|
-
* transformPlugin when parsing and evaluating modules.
|
|
16
|
-
*/
|
|
17
|
-
babelOptions?: Pick<StrictOptions['babelOptions'], 'plugins' | 'presets'>;
|
|
18
16
|
/** The set of rules that defines how the matched files will be transformed during the evaluation. */
|
|
19
|
-
evaluationRules?:
|
|
17
|
+
evaluationRules?: EvalRule[];
|
|
20
18
|
/** Plugins for extending AST evaluation with custom node handling. */
|
|
21
19
|
astEvaluationPlugins?: AstEvaluatorPlugin[];
|
|
20
|
+
/**
|
|
21
|
+
* Collects performance issues (CJS modules, barrel re-exports) during evaluation.
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
collectPerfIssues?: boolean;
|
|
22
25
|
};
|
|
23
26
|
export type TransformResult = {
|
|
24
27
|
code: string;
|
|
25
28
|
cssRulesByBucket?: CSSRulesByBucket;
|
|
26
29
|
usedProcessing: boolean;
|
|
27
30
|
usedVMForEvaluation: boolean;
|
|
31
|
+
perfIssues?: TransformPerfIssue[];
|
|
28
32
|
};
|
|
29
33
|
/**
|
|
30
34
|
* Transforms passed source code with oxc-parser and oxc-walker instead of Babel.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts ESM import/export syntax to CJS require/exports equivalents.
|
|
3
|
+
* This is needed because the VM evaluator wraps code in `(function(exports) { ... })(exports)`
|
|
4
|
+
* which cannot contain ESM syntax.
|
|
5
|
+
*/
|
|
6
|
+
export declare function convertESMtoCJS(code: string, filename: string): string;
|