@griffel/transform 1.2.0 → 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 +24 -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 +3 -3
- package/transform.js +237 -178
- 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,34 @@
|
|
|
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
|
+
|
|
20
|
+
## 1.2.1
|
|
21
|
+
|
|
22
|
+
Fri, 06 Mar 2026 15:56:28 GMT
|
|
23
|
+
|
|
24
|
+
### Patches
|
|
25
|
+
|
|
26
|
+
- refactor: remove cookModuleId from module evaluation (olfedias@microsoft.com)
|
|
27
|
+
- Bump @griffel/core to v1.20.1
|
|
28
|
+
|
|
7
29
|
## 1.2.0
|
|
8
30
|
|
|
9
|
-
Fri, 06 Mar 2026 08:
|
|
31
|
+
Fri, 06 Mar 2026 08:17:05 GMT
|
|
10
32
|
|
|
11
33
|
### Minor changes
|
|
12
34
|
|
|
@@ -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: (rawId: 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": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"./package.json": "./package.json"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@griffel/core": "^1.20.
|
|
20
|
-
"@
|
|
19
|
+
"@griffel/core": "^1.20.1",
|
|
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
|
};
|
|
@@ -168,35 +297,23 @@ const createCustomDebug = (depth) => (namespaces, arg1, ...args) => {
|
|
|
168
297
|
const modulePrefix = depth === 0 ? "module" : `sub-module-${depth}`;
|
|
169
298
|
debug(`${modulePrefix}:${namespaces}`, arg1, ...args);
|
|
170
299
|
};
|
|
171
|
-
const BABEL_ESM = "/@babel/runtime/helpers/esm/";
|
|
172
|
-
const BABEL_CJS = "/@babel/runtime/helpers/";
|
|
173
|
-
const SWC_HELPERS_RE = /(@swc\/helpers\/)src(\/.+)\.mjs/;
|
|
174
|
-
const cookModuleId = (rawId) => {
|
|
175
|
-
const babelESMIndex = rawId.indexOf(BABEL_ESM);
|
|
176
|
-
if (babelESMIndex !== -1) {
|
|
177
|
-
return rawId.slice(0, babelESMIndex) + BABEL_CJS + rawId.slice(babelESMIndex + BABEL_ESM.length);
|
|
178
|
-
}
|
|
179
|
-
const swcHelpersIndex = rawId.indexOf("@swc/helpers/src/");
|
|
180
|
-
if (swcHelpersIndex === -1) {
|
|
181
|
-
return rawId.replace(SWC_HELPERS_RE, "$1lib$2.js");
|
|
182
|
-
}
|
|
183
|
-
return rawId;
|
|
184
|
-
};
|
|
185
300
|
class Module {
|
|
186
301
|
id;
|
|
187
302
|
filename;
|
|
188
|
-
|
|
303
|
+
rules;
|
|
189
304
|
imports = null;
|
|
190
305
|
dependencies = null;
|
|
191
306
|
transform = null;
|
|
307
|
+
static extensions = /* @__PURE__ */ new Set([".json", ".js", ".jsx", ".ts", ".tsx", ".cjs", ".mjs", ".mts", ".cts"]);
|
|
192
308
|
exports = {};
|
|
193
|
-
|
|
309
|
+
resolveFilename;
|
|
194
310
|
debug;
|
|
195
311
|
debuggerDepth;
|
|
196
|
-
constructor(filename,
|
|
312
|
+
constructor(filename, rules, resolveFilename, debuggerDepth = 0) {
|
|
197
313
|
this.id = filename;
|
|
198
314
|
this.filename = filename;
|
|
199
|
-
this.
|
|
315
|
+
this.rules = rules;
|
|
316
|
+
this.resolveFilename = resolveFilename;
|
|
200
317
|
this.debuggerDepth = debuggerDepth;
|
|
201
318
|
this.debug = createCustomDebug(debuggerDepth);
|
|
202
319
|
Object.defineProperties(this, {
|
|
@@ -218,40 +335,16 @@ class Module {
|
|
|
218
335
|
}
|
|
219
336
|
});
|
|
220
337
|
this.exports = {};
|
|
221
|
-
this.extensions = [".json", ".js", ".jsx", ".ts", ".tsx", ".cjs"];
|
|
222
338
|
this.debug("prepare", filename);
|
|
223
339
|
}
|
|
224
|
-
resolve = (rawId) => {
|
|
225
|
-
const id = cookModuleId(rawId);
|
|
226
|
-
const extensions = NativeModule._extensions;
|
|
227
|
-
const added = [];
|
|
228
|
-
try {
|
|
229
|
-
this.extensions.forEach((ext) => {
|
|
230
|
-
if (ext in extensions) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
extensions[ext] = NOOP;
|
|
234
|
-
added.push(ext);
|
|
235
|
-
});
|
|
236
|
-
return Module._resolveFilename(id, this);
|
|
237
|
-
} finally {
|
|
238
|
-
added.forEach((ext) => delete extensions[ext]);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
340
|
require = Object.assign(
|
|
242
|
-
(
|
|
243
|
-
const id = cookModuleId(rawId);
|
|
341
|
+
(id) => {
|
|
244
342
|
this.debug("require", id);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
return require(id);
|
|
248
|
-
}
|
|
249
|
-
return null;
|
|
250
|
-
}
|
|
251
|
-
const filename = this.resolve(id);
|
|
252
|
-
if (filename === id && !path.isAbsolute(id)) {
|
|
343
|
+
const resolved = this.resolveFilename(id, this);
|
|
344
|
+
if (resolved.builtin) {
|
|
253
345
|
throw new Error(`Unable to import "${id}". Importing Node builtins is not supported in the sandbox.`);
|
|
254
346
|
}
|
|
347
|
+
const filename = resolved.path;
|
|
255
348
|
this.dependencies?.push(id);
|
|
256
349
|
let cacheKey = filename;
|
|
257
350
|
let only = [];
|
|
@@ -265,12 +358,13 @@ class Module {
|
|
|
265
358
|
let m = cache[cacheKey];
|
|
266
359
|
if (!m) {
|
|
267
360
|
this.debug("cached:not-exist", id);
|
|
268
|
-
m = new Module(filename, this.
|
|
361
|
+
m = new Module(filename, this.rules, this.resolveFilename, this.debuggerDepth + 1);
|
|
269
362
|
m.transform = this.transform;
|
|
270
363
|
cache[cacheKey] = m;
|
|
271
|
-
|
|
364
|
+
const ext = path.extname(filename).toLowerCase();
|
|
365
|
+
if (Module.extensions.has(ext)) {
|
|
272
366
|
const code = fs.readFileSync(filename, "utf-8");
|
|
273
|
-
if (
|
|
367
|
+
if (ext === ".json") {
|
|
274
368
|
m.exports = JSON.parse(code);
|
|
275
369
|
} else {
|
|
276
370
|
m.evaluate(code, only.includes("*") ? ["*"] : only);
|
|
@@ -286,16 +380,16 @@ class Module {
|
|
|
286
380
|
{
|
|
287
381
|
ensure: NOOP,
|
|
288
382
|
cache,
|
|
289
|
-
resolve: this.
|
|
383
|
+
resolve: (id) => this.resolveFilename(id, this).path
|
|
290
384
|
}
|
|
291
385
|
);
|
|
292
386
|
evaluate(text, only = null) {
|
|
293
387
|
const { filename } = this;
|
|
294
388
|
let action = "ignore";
|
|
295
|
-
for (let i = this.
|
|
296
|
-
const { test } = this.
|
|
297
|
-
if (!test || (typeof test === "function" ? test(filename) : test
|
|
298
|
-
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;
|
|
299
393
|
break;
|
|
300
394
|
}
|
|
301
395
|
}
|
|
@@ -309,13 +403,13 @@ class Module {
|
|
|
309
403
|
this.debug("ignore", `${filename}`);
|
|
310
404
|
code = text;
|
|
311
405
|
} else {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
+
}
|
|
319
413
|
this.debug("evaluate", `${this.filename} (only ${(only || []).join(", ")}):
|
|
320
414
|
${code}`);
|
|
321
415
|
}
|
|
@@ -331,6 +425,7 @@ ${code}`);
|
|
|
331
425
|
setImmediate: NOOP,
|
|
332
426
|
setInterval: NOOP,
|
|
333
427
|
setTimeout: NOOP,
|
|
428
|
+
fetch: NOOP,
|
|
334
429
|
global,
|
|
335
430
|
process: mockProcess,
|
|
336
431
|
module: this,
|
|
@@ -348,13 +443,6 @@ ${code}`);
|
|
|
348
443
|
static invalidateEvalCache = () => {
|
|
349
444
|
clear();
|
|
350
445
|
};
|
|
351
|
-
// Alias to resolve the module using node's resolve algorithm
|
|
352
|
-
// This static property can be overridden by the webpack loader
|
|
353
|
-
// This allows us to use webpack's module resolution algorithm
|
|
354
|
-
static _resolveFilename = (id, options) => NativeModule._resolveFilename(
|
|
355
|
-
id,
|
|
356
|
-
options
|
|
357
|
-
);
|
|
358
446
|
static _nodeModulePaths = (filename) => NativeModule._nodeModulePaths(filename);
|
|
359
447
|
}
|
|
360
448
|
const DEOPT = /* @__PURE__ */ Symbol("deopt");
|
|
@@ -385,17 +473,17 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
385
473
|
}
|
|
386
474
|
function evaluateObjectExpression(node2) {
|
|
387
475
|
const obj = {};
|
|
388
|
-
for (const
|
|
389
|
-
if (
|
|
476
|
+
for (const prop2 of node2.properties) {
|
|
477
|
+
if (prop2.type !== "Property" || prop2.kind !== "init") {
|
|
390
478
|
return DEOPT;
|
|
391
479
|
}
|
|
392
480
|
let key;
|
|
393
|
-
if (
|
|
481
|
+
if (prop2.computed) {
|
|
394
482
|
return DEOPT;
|
|
395
|
-
} else if (
|
|
396
|
-
key =
|
|
397
|
-
} else if (
|
|
398
|
-
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;
|
|
399
487
|
if (typeof keyLiteral.value === "string" || typeof keyLiteral.value === "number") {
|
|
400
488
|
key = String(keyLiteral.value);
|
|
401
489
|
} else {
|
|
@@ -404,7 +492,7 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
404
492
|
} else {
|
|
405
493
|
return DEOPT;
|
|
406
494
|
}
|
|
407
|
-
const value = evaluateNode(
|
|
495
|
+
const value = evaluateNode(prop2.value);
|
|
408
496
|
if (value === DEOPT) {
|
|
409
497
|
return DEOPT;
|
|
410
498
|
}
|
|
@@ -427,34 +515,20 @@ function astEvaluator(node, programAst, plugins = []) {
|
|
|
427
515
|
function isError(e) {
|
|
428
516
|
return Object.prototype.toString.call(e) === "[object Error]";
|
|
429
517
|
}
|
|
430
|
-
function vmEvaluator(sourceCode, filename, expressionCode,
|
|
518
|
+
function vmEvaluator(sourceCode, filename, expressionCode, evaluationRules, resolveFilename) {
|
|
431
519
|
const codeForEvaluation = `
|
|
432
520
|
${sourceCode}
|
|
433
521
|
|
|
434
|
-
const __mkPreval = (() => {
|
|
522
|
+
export const __mkPreval = (() => {
|
|
435
523
|
try {
|
|
436
524
|
return ([${expressionCode}]);
|
|
437
525
|
} catch (e) {
|
|
438
526
|
return e;
|
|
439
527
|
}
|
|
440
528
|
})();
|
|
441
|
-
|
|
442
|
-
if (typeof module !== 'undefined' && module.exports) {
|
|
443
|
-
module.exports = { __mkPreval };
|
|
444
|
-
}
|
|
445
529
|
`;
|
|
446
530
|
try {
|
|
447
|
-
const
|
|
448
|
-
displayName: false,
|
|
449
|
-
evaluate: true,
|
|
450
|
-
rules: evaluationRules,
|
|
451
|
-
babelOptions: {
|
|
452
|
-
...babelOptions,
|
|
453
|
-
configFile: false,
|
|
454
|
-
babelrc: false
|
|
455
|
-
}
|
|
456
|
-
};
|
|
457
|
-
const mod = new Module(filename, options);
|
|
531
|
+
const mod = new Module(filename, evaluationRules, resolveFilename);
|
|
458
532
|
mod.evaluate(codeForEvaluation, ["__mkPreval"]);
|
|
459
533
|
const result = mod.exports.__mkPreval;
|
|
460
534
|
if (isError(result)) {
|
|
@@ -465,10 +539,10 @@ if (typeof module !== 'undefined' && module.exports) {
|
|
|
465
539
|
return { confident: false, error: err };
|
|
466
540
|
}
|
|
467
541
|
}
|
|
468
|
-
function batchEvaluator(sourceCode, filename, styleCalls,
|
|
542
|
+
function batchEvaluator(sourceCode, filename, styleCalls, evaluationRules, resolveFilename, programAst, astEvaluationPlugins = []) {
|
|
469
543
|
const evaluationResults = new Array(styleCalls.length);
|
|
470
|
-
const
|
|
471
|
-
let
|
|
544
|
+
const vmIndices = [];
|
|
545
|
+
let expressionCode = "";
|
|
472
546
|
for (let i = 0; i < styleCalls.length; i++) {
|
|
473
547
|
const styleCall = styleCalls[i];
|
|
474
548
|
const staticResult = astEvaluator(styleCall.argumentNode, programAst, astEvaluationPlugins);
|
|
@@ -476,16 +550,19 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
|
|
|
476
550
|
evaluationResults[i] = staticResult.value;
|
|
477
551
|
continue;
|
|
478
552
|
}
|
|
479
|
-
|
|
480
|
-
|
|
553
|
+
if (expressionCode.length > 0) {
|
|
554
|
+
expressionCode += ",";
|
|
555
|
+
}
|
|
556
|
+
expressionCode += styleCall.argumentCode;
|
|
557
|
+
vmIndices.push(i);
|
|
481
558
|
}
|
|
482
|
-
if (
|
|
559
|
+
if (vmIndices.length === 0) {
|
|
483
560
|
return {
|
|
484
561
|
usedVMForEvaluation: false,
|
|
485
562
|
evaluationResults
|
|
486
563
|
};
|
|
487
564
|
}
|
|
488
|
-
const vmResult = vmEvaluator(sourceCode, filename,
|
|
565
|
+
const vmResult = vmEvaluator(sourceCode, filename, expressionCode, evaluationRules, resolveFilename);
|
|
489
566
|
if (!vmResult.confident) {
|
|
490
567
|
if (vmResult.error) {
|
|
491
568
|
throw vmResult.error;
|
|
@@ -494,45 +571,14 @@ function batchEvaluator(sourceCode, filename, styleCalls, babelOptions, evaluati
|
|
|
494
571
|
}
|
|
495
572
|
}
|
|
496
573
|
const vmValues = vmResult.value;
|
|
497
|
-
for (let i = 0; i <
|
|
498
|
-
|
|
499
|
-
continue;
|
|
500
|
-
}
|
|
501
|
-
evaluationResults[i] = vmValues[i];
|
|
574
|
+
for (let i = 0; i < vmIndices.length; i++) {
|
|
575
|
+
evaluationResults[vmIndices[i]] = vmValues[i];
|
|
502
576
|
}
|
|
503
577
|
return {
|
|
504
578
|
usedVMForEvaluation: true,
|
|
505
579
|
evaluationResults
|
|
506
580
|
};
|
|
507
581
|
}
|
|
508
|
-
const CJS_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".json"]);
|
|
509
|
-
const ESM_EXTENSIONS = /* @__PURE__ */ new Set([".mjs", ".mts"]);
|
|
510
|
-
const useRawTransfer = rawTransferSupported();
|
|
511
|
-
const NODE_MODULES_RE = /[/\\]node_modules[/\\]/;
|
|
512
|
-
function createHybridEvaluator(shakerEvaluator2) {
|
|
513
|
-
return (filename, options, text, only) => {
|
|
514
|
-
if (!NODE_MODULES_RE.test(filename)) {
|
|
515
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
516
|
-
}
|
|
517
|
-
const ext = extname(filename);
|
|
518
|
-
if (CJS_EXTENSIONS.has(ext)) {
|
|
519
|
-
return [text, null];
|
|
520
|
-
}
|
|
521
|
-
if (ESM_EXTENSIONS.has(ext)) {
|
|
522
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
523
|
-
}
|
|
524
|
-
const parseResult = parseSync(filename, text, {
|
|
525
|
-
sourceType: "unambiguous",
|
|
526
|
-
...useRawTransfer && { experimentalLazy: true }
|
|
527
|
-
});
|
|
528
|
-
const isESM = parseResult.module.hasModuleSyntax;
|
|
529
|
-
parseResult.dispose?.();
|
|
530
|
-
if (!isESM) {
|
|
531
|
-
return [text, null];
|
|
532
|
-
}
|
|
533
|
-
return shakerEvaluator2(filename, options, text, only);
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
582
|
function evaluateTemplateLiteralWithTokens(node) {
|
|
537
583
|
let result = "";
|
|
538
584
|
for (let i = 0; i < node.quasis.length; i++) {
|
|
@@ -584,7 +630,18 @@ function dedupeCSSRules(cssRulesByBucket) {
|
|
|
584
630
|
})
|
|
585
631
|
);
|
|
586
632
|
}
|
|
587
|
-
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
|
+
}
|
|
588
645
|
const RUNTIME_IDENTIFIERS = /* @__PURE__ */ new Map([
|
|
589
646
|
["makeStyles", "__css"],
|
|
590
647
|
["makeResetStyles", "__resetCSS"],
|
|
@@ -650,13 +707,14 @@ function concatCSSRulesByBucket(bucketA = {}, bucketB) {
|
|
|
650
707
|
return bucketA;
|
|
651
708
|
}
|
|
652
709
|
function transformSync(sourceCode, options) {
|
|
710
|
+
const perfIssues = options.collectPerfIssues ? [] : void 0;
|
|
653
711
|
const {
|
|
654
|
-
babelOptions = {},
|
|
655
712
|
filename,
|
|
713
|
+
resolveModule,
|
|
656
714
|
classNameHashSalt = "",
|
|
657
715
|
generateMetadata = false,
|
|
658
716
|
modules = ["@griffel/core", "@griffel/react", "@fluentui/react-components"],
|
|
659
|
-
evaluationRules = [{ action:
|
|
717
|
+
evaluationRules = [{ action: perfIssues ? wrapWithPerfIssues(shakerEvaluator, perfIssues) : shakerEvaluator }],
|
|
660
718
|
astEvaluationPlugins = [fluentTokensPlugin]
|
|
661
719
|
} = options;
|
|
662
720
|
if (!filename) {
|
|
@@ -756,8 +814,8 @@ function transformSync(sourceCode, options) {
|
|
|
756
814
|
sourceCode,
|
|
757
815
|
filename,
|
|
758
816
|
styleCalls,
|
|
759
|
-
babelOptions,
|
|
760
817
|
evaluationRules,
|
|
818
|
+
resolveModule,
|
|
761
819
|
programAst,
|
|
762
820
|
astEvaluationPlugins
|
|
763
821
|
);
|
|
@@ -820,7 +878,8 @@ function transformSync(sourceCode, options) {
|
|
|
820
878
|
code: magicString.toString(),
|
|
821
879
|
cssRulesByBucket,
|
|
822
880
|
usedProcessing: true,
|
|
823
|
-
usedVMForEvaluation
|
|
881
|
+
usedVMForEvaluation,
|
|
882
|
+
perfIssues
|
|
824
883
|
};
|
|
825
884
|
}
|
|
826
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;
|