@plumeria/turbopack-loader 18.4.2 → 18.5.1

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.
@@ -1,2 +1,2 @@
1
- export declare function acquireLock(lockDir: string, delayMs?: number, maxDelayMs?: number): Promise<void>;
1
+ export declare function acquireLock(lockDir: string, delayMs?: number, maxDelayMs?: number, timeoutMs?: number): Promise<void>;
2
2
  export declare function releaseLockSync(lockDir: string): void;
package/dist/file-lock.js CHANGED
@@ -37,7 +37,8 @@ exports.acquireLock = acquireLock;
37
37
  exports.releaseLockSync = releaseLockSync;
38
38
  const fs = __importStar(require("fs"));
39
39
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
40
- async function acquireLock(lockDir, delayMs = 2, maxDelayMs = 50) {
40
+ async function acquireLock(lockDir, delayMs = 2, maxDelayMs = 50, timeoutMs = 30_000) {
41
+ const started = Date.now();
41
42
  let delay = delayMs;
42
43
  while (true) {
43
44
  try {
@@ -46,7 +47,11 @@ async function acquireLock(lockDir, delayMs = 2, maxDelayMs = 50) {
46
47
  }
47
48
  catch (err) {
48
49
  if (err.code === 'EEXIST') {
49
- await sleep(delay);
50
+ const remaining = timeoutMs - (Date.now() - started);
51
+ if (remaining <= 0) {
52
+ throw new Error(`Plumeria: Timed out waiting for CSS lock "${lockDir}". If no build is running, remove the stale lock directory and retry.`, { cause: err });
53
+ }
54
+ await sleep(Math.min(delay, remaining));
50
55
  delay = Math.min(delay * 2, maxDelayMs);
51
56
  continue;
52
57
  }
package/dist/index.js CHANGED
@@ -77,7 +77,10 @@ async function generateProductionCss(virtualFilePath, options) {
77
77
  }
78
78
  const ensureProductionCss = (virtualFilePath, options) => {
79
79
  if (!productionCss) {
80
- productionCss = generateProductionCss(virtualFilePath, options);
80
+ productionCss = generateProductionCss(virtualFilePath, options).catch((error) => {
81
+ productionCss = null;
82
+ throw error;
83
+ });
81
84
  }
82
85
  return productionCss;
83
86
  };
@@ -127,6 +130,26 @@ const destructuredPropAliases = (fn) => {
127
130
  }
128
131
  return aliases;
129
132
  };
133
+ const spreadStyleMessage = (source) => `Plumeria: Spread elements in a style array are not supported: "...${source}". ` +
134
+ `List each style explicitly.`;
135
+ const resolveLocalStyleAlias = (aliases, expression) => {
136
+ let current = expression;
137
+ const seen = new Set();
138
+ while (utils_1.t.isIdentifier(current)) {
139
+ const name = current.value;
140
+ if (seen.has(name))
141
+ break;
142
+ seen.add(name);
143
+ const candidates = aliases[name];
144
+ if (!candidates || candidates.length === 0)
145
+ break;
146
+ const candidate = candidates.find((candidate) => candidate.context === current.ctxt);
147
+ if (!candidate)
148
+ break;
149
+ current = candidate.expression;
150
+ }
151
+ return current;
152
+ };
130
153
  const isStaticArgValue = (node) => node.type === 'StringLiteral' ||
131
154
  node.type === 'NumericLiteral' ||
132
155
  node.type === 'BooleanLiteral' ||
@@ -213,6 +236,7 @@ async function loader(source) {
213
236
  utils_1.t.isFunctionExpression(node)) {
214
237
  const rootId = (0, utils_1.getRootIdentifier)(node);
215
238
  const isPlumeriaStyle = rootId &&
239
+ isVisibleReference(node) &&
216
240
  ((localCreateStyles[rootId] !== undefined &&
217
241
  localCreateStyles[rootId].type !== 'constant') ||
218
242
  mergedCreateTable[rootId] !== undefined ||
@@ -229,6 +253,10 @@ async function loader(source) {
229
253
  }
230
254
  }
231
255
  };
256
+ const scannedTables = (0, utils_1.scanAll)();
257
+ const ownFailure = (0, utils_1.resolveFileError)(resourcePath, '');
258
+ if (ownFailure)
259
+ throwCompilationError(`Plumeria: ${ownFailure.message}`);
232
260
  for (const node of ast.body) {
233
261
  if (node.type === 'ImportDeclaration') {
234
262
  const sourcePath = node.source.value;
@@ -242,7 +270,6 @@ async function loader(source) {
242
270
  }
243
271
  }
244
272
  }
245
- const scannedTables = (0, utils_1.scanAll)();
246
273
  if (scannedTables.componentPropsTable) {
247
274
  const parentFiles = new Set();
248
275
  for (const compKey of Object.keys(scannedTables.componentPropsTable)) {
@@ -263,11 +290,32 @@ async function loader(source) {
263
290
  }
264
291
  const components = [];
265
292
  const propAliases = new Map();
293
+ const propDefaults = new Map();
294
+ const declaredProps = new Map();
266
295
  const addComponent = (name, fn) => {
267
296
  components.push({ name, node: fn });
297
+ const first = fn.params[0];
298
+ const pattern = unwrapPatternDefault(first?.pat ?? first);
299
+ const defaults = new Map();
300
+ for (const item of pattern?.properties ?? []) {
301
+ if (item.type === 'AssignmentPatternProperty' && item.value)
302
+ defaults.set(item.key.value, item.value);
303
+ if (item.type === 'KeyValuePatternProperty' &&
304
+ item.value?.type === 'AssignmentPattern')
305
+ defaults.set(item.key.value, item.value.right);
306
+ }
307
+ propDefaults.set(name, defaults);
268
308
  const aliases = destructuredPropAliases(fn);
269
309
  if (aliases.size > 0)
270
310
  propAliases.set(name, aliases);
311
+ const declared = new Set();
312
+ for (const item of pattern?.properties ?? []) {
313
+ const key = item.key;
314
+ if (utils_1.t.isIdentifier(key) || utils_1.t.isStringLiteral(key))
315
+ declared.add(String(key.value));
316
+ }
317
+ if (declared.size > 0)
318
+ declaredProps.set(name, declared);
271
319
  };
272
320
  for (const node of ast.body) {
273
321
  const statement = unwrapExport(node);
@@ -500,24 +548,83 @@ async function loader(source) {
500
548
  const checkStyleAliasAssignment = (decl) => {
501
549
  if (!utils_1.t.isIdentifier(decl.id) || !decl.init)
502
550
  return;
503
- const init = decl.init;
551
+ const init = (0, utils_1.unwrapExpression)(decl.init);
504
552
  if (utils_1.t.isMemberExpression(init) && utils_1.t.isIdentifier(init.object)) {
505
553
  const objName = init.object.value;
506
554
  if (localCreateStyles[objName] !== undefined ||
507
555
  mergedCreateTable[objName] !== undefined) {
508
- localStyleAliases[decl.id.value] = init;
556
+ (localStyleAliases[decl.id.value] ??= []).push({
557
+ expression: init,
558
+ context: decl.id.ctxt,
559
+ });
509
560
  }
510
561
  }
511
562
  };
512
563
  const replacements = [];
564
+ const deferredSources = [];
565
+ const deferSource = (node, stripObject = false) => {
566
+ const token = `__plumeria_preserved_${deferredSources.length}__`;
567
+ deferredSources.push({
568
+ token,
569
+ start: node.span.start - baseByteOffset,
570
+ end: node.span.end - baseByteOffset,
571
+ stripObject,
572
+ });
573
+ return token;
574
+ };
513
575
  const dynamicFnCalls = [];
514
576
  const processedDecls = new Set();
577
+ const separatelyExported = new Set();
578
+ for (const statement of ast.body) {
579
+ if (statement.type !== 'ExportNamedDeclaration' || statement.source)
580
+ continue;
581
+ for (const specifier of statement.specifiers) {
582
+ if (specifier.type === 'ExportSpecifier' &&
583
+ utils_1.t.isIdentifier(specifier.orig)) {
584
+ separatelyExported.add(specifier.orig.value);
585
+ }
586
+ }
587
+ }
515
588
  const idSpans = new Set();
516
589
  const excludedSpans = new Set();
517
590
  const referenceIdents = (0, utils_1.collectReferenceIdentifiers)(ast);
591
+ const topLevelDeclarators = new Set();
592
+ for (const statement of ast.body) {
593
+ const declaration = unwrapExport(statement);
594
+ if (utils_1.t.isVariableDeclaration(declaration)) {
595
+ declaration.declarations.forEach((decl) => topLevelDeclarators.add(decl));
596
+ }
597
+ }
598
+ const unwrapStyleExpression = (node) => {
599
+ while (node &&
600
+ [
601
+ 'ParenthesisExpression',
602
+ 'TsAsExpression',
603
+ 'TsSatisfiesExpression',
604
+ 'TsNonNullExpression',
605
+ 'TsConstAssertion',
606
+ 'TsTypeAssertion',
607
+ ].includes(node.type))
608
+ node = node.expression;
609
+ return node;
610
+ };
611
+ const literalObjectArgument = (node, seen = new Set()) => {
612
+ node = unwrapStyleExpression(node);
613
+ if (utils_1.t.isObjectExpression(node))
614
+ return node;
615
+ if (!utils_1.t.isIdentifier(node) || seen.has(node.value))
616
+ return null;
617
+ seen.add(node.value);
618
+ const declaration = [...topLevelDeclarators].find((decl) => utils_1.t.isIdentifier(decl.id) &&
619
+ decl.id.value === node.value);
620
+ return declaration?.init
621
+ ? literalObjectArgument(declaration.init, seen)
622
+ : null;
623
+ };
624
+ const registeredStyleCalls = new Set();
518
625
  const registerStyle = (node, declSpan, isExported) => {
519
626
  let propName;
520
- const init = node.init;
627
+ const init = unwrapStyleExpression(node.init);
521
628
  if (utils_1.t.isIdentifier(node.id) &&
522
629
  init &&
523
630
  utils_1.t.isCallExpression(init) &&
@@ -542,6 +649,19 @@ async function loader(source) {
542
649
  }
543
650
  }
544
651
  if (propName && init && utils_1.t.isCallExpression(init)) {
652
+ if (['create', 'createTheme', 'createStatic'].includes(propName) &&
653
+ !topLevelDeclarators.has(node)) {
654
+ throwCompilationError(`Plumeria: css.${propName} must be assigned to a top-level variable so its styles can be resolved across files. Move this declaration outside the function or block.`, node);
655
+ }
656
+ if (['create', 'createTheme', 'createStatic'].includes(propName)) {
657
+ const argumentIndex = propName === 'createTheme' ? 1 : 0;
658
+ const argument = init.arguments[argumentIndex];
659
+ const object = argument && literalObjectArgument(argument.expression);
660
+ if (!object)
661
+ throwCompilationError(`Plumeria: css.${propName} needs a style object it can read at build time. Pass an object literal or a top-level constant containing one.`, init);
662
+ argument.expression = object;
663
+ registeredStyleCalls.add(init.span.start);
664
+ }
545
665
  if (propName === 'create' &&
546
666
  utils_1.t.isObjectExpression(init.arguments[0].expression)) {
547
667
  const obj = (0, utils_1.objectExpressionToObject)(init.arguments[0].expression, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
@@ -712,7 +832,9 @@ async function loader(source) {
712
832
  if (processedDecls.has(node))
713
833
  return;
714
834
  node.declarations.forEach((decl) => {
715
- registerStyle(decl, node.span, false);
835
+ registerStyle(decl, node.span, node.declarations.length > 1 ||
836
+ (utils_1.t.isIdentifier(decl.id) &&
837
+ separatelyExported.has(decl.id.value)));
716
838
  checkStyleAliasAssignment(decl);
717
839
  });
718
840
  },
@@ -737,6 +859,10 @@ async function loader(source) {
737
859
  }
738
860
  }
739
861
  if (propName) {
862
+ if (['create', 'createTheme', 'createStatic'].includes(propName) &&
863
+ !registeredStyleCalls.has(node.span.start)) {
864
+ throwCompilationError(`Plumeria: css.${propName} must be assigned to a named top-level variable. Destructuring, assignment statements, and default-exported calls cannot be compiled.`, node);
865
+ }
740
866
  const args = node.arguments;
741
867
  if (propName === 'keyframes' && args.length > 0) {
742
868
  const expr = args[0].expression;
@@ -802,12 +928,17 @@ async function loader(source) {
802
928
  const jsxOpeningElementMap = new Map();
803
929
  const componentParamNames = new Set();
804
930
  const addFirstParamName = (fn) => {
805
- const p = fn.params[0];
931
+ const first = fn.params[0];
932
+ const p = unwrapPatternDefault(first?.pat ?? first);
806
933
  if (utils_1.t.isIdentifier(p)) {
807
934
  componentParamNames.add(p.value);
808
935
  }
809
- else if (p?.pat && utils_1.t.isIdentifier(p.pat)) {
810
- componentParamNames.add(p.pat.value);
936
+ else if (p?.type === 'ObjectPattern') {
937
+ for (const item of p.properties) {
938
+ if (item.type === 'RestElement' && utils_1.t.isIdentifier(item.argument)) {
939
+ componentParamNames.add(item.argument.value);
940
+ }
941
+ }
811
942
  }
812
943
  };
813
944
  for (const node of ast.body) {
@@ -843,7 +974,36 @@ async function loader(source) {
843
974
  const end = node.span.end - baseByteOffset;
844
975
  return sourceBuffer.subarray(start, end).toString('utf-8');
845
976
  };
977
+ const isVisibleReference = (expr) => {
978
+ if (utils_1.t.isIdentifier(expr))
979
+ return referenceIdents.references.has(expr.span.start);
980
+ if (utils_1.t.isMemberExpression(expr))
981
+ return isVisibleReference(expr.object);
982
+ if (utils_1.t.isCallExpression(expr) &&
983
+ expr.callee.type !== 'Super' &&
984
+ expr.callee.type !== 'Import')
985
+ return isVisibleReference(expr.callee);
986
+ return true;
987
+ };
846
988
  const resolveStyleObject = (expr) => {
989
+ expr = (0, utils_1.unwrapExpression)(expr);
990
+ expr = resolveLocalStyleAlias(localStyleAliases, expr);
991
+ if (!isVisibleReference(expr))
992
+ return null;
993
+ if (expr.type === 'ArrayExpression') {
994
+ let merged = {};
995
+ for (const element of expr.elements ?? []) {
996
+ if (!element)
997
+ continue;
998
+ if (element.spread)
999
+ throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
1000
+ const style = resolveStyleObject(element.expression);
1001
+ if (!style)
1002
+ return null;
1003
+ merged = (0, utils_1.deepMerge)(merged, style);
1004
+ }
1005
+ return merged;
1006
+ }
847
1007
  if (utils_1.t.isObjectExpression(expr)) {
848
1008
  return (0, utils_1.objectExpressionToObject)(expr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
849
1009
  }
@@ -903,12 +1063,34 @@ async function loader(source) {
903
1063
  return Boolean(localCreateStyles[callee.object.value]?.functions?.[callee.property.value] ??
904
1064
  createFunctionImportMap[callee.object.value]?.[callee.property.value]);
905
1065
  };
1066
+ const carriesStyleReference = (expression) => {
1067
+ const node = (0, utils_1.unwrapExpression)(expression);
1068
+ if (node.type === 'ArrayExpression')
1069
+ return node.elements.some((element) => !!element && carriesStyleReference(element.expression));
1070
+ if (isStyleFunctionCall(node))
1071
+ return true;
1072
+ if (utils_1.t.isObjectExpression(node))
1073
+ return false;
1074
+ return resolveStyleObject(node) !== null;
1075
+ };
1076
+ const assertNoStyleArraySpread = (expression) => {
1077
+ const node = (0, utils_1.unwrapExpression)(expression);
1078
+ if (node.type !== 'ArrayExpression')
1079
+ return;
1080
+ const spread = node.elements.find((element) => element?.spread);
1081
+ if (!spread)
1082
+ return;
1083
+ if (carriesStyleReference(node))
1084
+ throwCompilationError(spreadStyleMessage(getSource(spread.expression)), spread.expression);
1085
+ };
906
1086
  const resolveDynamicCall = (expr, forceRuntime = false) => {
907
1087
  if (!utils_1.t.isCallExpression(expr) || !utils_1.t.isMemberExpression(expr.callee))
908
1088
  return null;
909
1089
  const callee = expr.callee;
910
1090
  if (!utils_1.t.isIdentifier(callee.object) || !utils_1.t.isIdentifier(callee.property))
911
1091
  return null;
1092
+ if (!isVisibleReference(callee.object))
1093
+ return null;
912
1094
  const styleInfo = localCreateStyles[callee.object.value];
913
1095
  const func = styleInfo?.functions?.[callee.property.value] ??
914
1096
  createFunctionImportMap[callee.object.value]?.[callee.property.value];
@@ -918,8 +1100,14 @@ async function loader(source) {
918
1100
  if (callArgs.some((a) => a.spread))
919
1101
  return null;
920
1102
  const tempStaticTable = { ...mergedStaticTable };
1103
+ const providedParams = new Set();
921
1104
  const runtime = [];
922
- const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)(argExpr, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
1105
+ const resolveObjectArg = (argExpr) => (0, utils_1.objectExpressionToObject)({
1106
+ ...argExpr,
1107
+ properties: argExpr.properties.filter((prop) => prop.type === 'Identifier' ||
1108
+ (prop.type === 'KeyValueProperty' &&
1109
+ isStaticArgValue(prop.value))),
1110
+ }, mergedStaticTable, mergedKeyframesTable, mergedViewTransitionTable, mergedCreateThemeHashTable, scannedTables.createThemeObjectTable, mergedCreateTable, mergedCreateStaticHashTable, scannedTables.createStaticObjectTable, mergedVariantsTable);
923
1111
  if (func.named) {
924
1112
  const argExpr = callArgs[0]?.expression;
925
1113
  if (callArgs.length > 1 ||
@@ -949,8 +1137,10 @@ async function loader(source) {
949
1137
  }
950
1138
  if (!forceRuntime &&
951
1139
  isStaticArgValue(source) &&
952
- argObj[key] !== undefined)
1140
+ argObj[key] !== undefined) {
953
1141
  tempStaticTable[local] = argObj[key];
1142
+ providedParams.add(local);
1143
+ }
954
1144
  else
955
1145
  runtime.push({ param: local, source });
956
1146
  });
@@ -961,8 +1151,10 @@ async function loader(source) {
961
1151
  return null;
962
1152
  const argObj = resolveObjectArg(callArgs[0].expression) ?? {};
963
1153
  func.params.forEach((p) => {
964
- if (argObj[p] !== undefined)
1154
+ if (argObj[p] !== undefined) {
965
1155
  tempStaticTable[p] = argObj[p];
1156
+ providedParams.add(p);
1157
+ }
966
1158
  });
967
1159
  }
968
1160
  else {
@@ -973,7 +1165,7 @@ async function loader(source) {
973
1165
  runtime.push({ param: p, source: callArg.expression });
974
1166
  });
975
1167
  }
976
- const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables);
1168
+ const resolved = (0, utils_1.resolveDynamicStyle)(func, runtime.map(({ param }) => param), tempStaticTable, dynamicStyleTables, providedParams);
977
1169
  if (!resolved)
978
1170
  return null;
979
1171
  const { style, varGroups } = resolved;
@@ -1010,10 +1202,7 @@ async function loader(source) {
1010
1202
  };
1011
1203
  const buildClassParts = (args, dynamicClassParts = [], existingClass = '', isStyleProp = false) => {
1012
1204
  args.forEach((arg) => {
1013
- const expr = arg.expression;
1014
- if (utils_1.t.isIdentifier(expr) && localStyleAliases[expr.value]) {
1015
- arg.expression = localStyleAliases[expr.value];
1016
- }
1205
+ arg.expression = resolveLocalStyleAlias(localStyleAliases, arg.expression);
1017
1206
  });
1018
1207
  const conditionals = [];
1019
1208
  const dynamicVars = [];
@@ -1041,6 +1230,8 @@ async function loader(source) {
1041
1230
  utils_1.t.isStringLiteral(node.property.expression)) {
1042
1231
  return null;
1043
1232
  }
1233
+ if (!isVisibleReference(node.object))
1234
+ return null;
1044
1235
  const varName = node.object.value;
1045
1236
  const obj = resolveCreateObject(varName);
1046
1237
  return obj ? { varName, keyExpr: node.property.expression, obj } : null;
@@ -1134,8 +1325,19 @@ async function loader(source) {
1134
1325
  return buildDecision(node, prefix, off, { n: 0 }, scoped);
1135
1326
  };
1136
1327
  const collectConditions = (node, currentTestStrings = [], argOrder) => {
1328
+ node = (0, utils_1.unwrapExpression)(node);
1329
+ node = resolveLocalStyleAlias(localStyleAliases, node);
1137
1330
  if (isNoOpStyle(node))
1138
1331
  return true;
1332
+ if (node.type === 'ArrayExpression') {
1333
+ return node.elements.every((element) => {
1334
+ if (!element)
1335
+ return true;
1336
+ if (element.spread)
1337
+ throwCompilationError(spreadStyleMessage(getSource(element.expression)), element.expression);
1338
+ return collectConditions(element.expression, currentTestStrings, argOrder);
1339
+ });
1340
+ }
1139
1341
  let branchStyle = resolveStyleObject(node);
1140
1342
  if (!branchStyle) {
1141
1343
  const dynamic = resolveDynamicCall(node);
@@ -1188,13 +1390,12 @@ async function loader(source) {
1188
1390
  return true;
1189
1391
  }
1190
1392
  }
1191
- collectConditions(node.consequent, [...currentTestStrings, `(${testSource})`], argOrder);
1192
- collectConditions(node.alternate, [...currentTestStrings, `!(${testSource})`], argOrder);
1193
- return true;
1393
+ const consequentHandled = collectConditions(node.consequent, [...currentTestStrings, `(${testSource})`], argOrder);
1394
+ const alternateHandled = collectConditions(node.alternate, [...currentTestStrings, `!(${testSource})`], argOrder);
1395
+ return consequentHandled && alternateHandled;
1194
1396
  }
1195
1397
  else if (node.type === 'BinaryExpression' && node.operator === '&&') {
1196
- collectConditions(node.right, [...currentTestStrings, `(${getSource(node.left)})`], argOrder);
1197
- return true;
1398
+ return collectConditions(node.right, [...currentTestStrings, `(${getSource(node.left)})`], argOrder);
1198
1399
  }
1199
1400
  else if (node.type === 'ParenthesisExpression') {
1200
1401
  return collectConditions(node.expression, currentTestStrings, argOrder);
@@ -1211,6 +1412,12 @@ async function loader(source) {
1211
1412
  utils_1.t.isIdentifier(expr.property);
1212
1413
  if (!utils_1.t.isIdentifier(expr) && !isParamMember)
1213
1414
  return false;
1415
+ const paramObject = isParamMember
1416
+ ? expr.object.value
1417
+ : undefined;
1418
+ const isPropsMember = Boolean(paramObject &&
1419
+ localCreateStyles[paramObject] === undefined &&
1420
+ mergedCreateTable[paramObject] === undefined);
1214
1421
  const varName = utils_1.t.isIdentifier(expr)
1215
1422
  ? expr.value
1216
1423
  : expr.property.value;
@@ -1235,8 +1442,42 @@ async function loader(source) {
1235
1442
  if (candidates.length > 0)
1236
1443
  possibilities = candidates;
1237
1444
  }
1238
- if (!possibilities || possibilities.length === 0)
1239
- return false;
1445
+ const fallback = owner && propDefaults.get(owner)?.get(propName);
1446
+ if (fallback) {
1447
+ const style = resolveStyleObject(fallback);
1448
+ if (style) {
1449
+ const atoms = {};
1450
+ (0, utils_1.getStyleRecords)(style).forEach((record) => {
1451
+ atoms[record.key] = record.hash;
1452
+ });
1453
+ const key = (0, zss_engine_1.genBase36Hash)(Object.values(atoms).join(' '), 1, 8);
1454
+ possibilities = [
1455
+ ...(possibilities ?? []),
1456
+ { key, styleObj: style },
1457
+ ];
1458
+ const span = fallback.span;
1459
+ {
1460
+ for (let i = replacements.length - 1; i >= 0; i--) {
1461
+ const replacement = replacements[i];
1462
+ if (replacement.start >= span.start - baseByteOffset &&
1463
+ replacement.end <= span.end - baseByteOffset)
1464
+ replacements.splice(i, 1);
1465
+ }
1466
+ excludeSubtreeSpans(fallback);
1467
+ replacements.push({
1468
+ start: span.start - baseByteOffset,
1469
+ end: span.end - baseByteOffset,
1470
+ content: JSON.stringify(key),
1471
+ });
1472
+ }
1473
+ }
1474
+ else {
1475
+ assertResolvable(fallback);
1476
+ }
1477
+ }
1478
+ if (!possibilities || possibilities.length === 0) {
1479
+ return Boolean(isPropsMember || (owner && declaredProps.get(owner)?.has(propName)));
1480
+ }
1240
1481
  const carriesVars = possibilities.some((entry) => entry.hasVars);
1241
1482
  if (carriesVars && !isStyleProp) {
1242
1483
  throwCompilationError(`Plumeria: "${varName}" carries a dynamic function key, and css.use() returns only a class name. ` +
@@ -1296,7 +1537,11 @@ async function loader(source) {
1296
1537
  hash = mergedVariantsTable[varName];
1297
1538
  if (hash && scannedTables.variantsObjectTable[hash])
1298
1539
  variantObj = scannedTables.variantsObjectTable[hash];
1299
- if (!variantObj && localCreateStyles[varName]?.obj)
1540
+ if (!isVisibleReference(expr))
1541
+ variantObj = undefined;
1542
+ if (isVisibleReference(expr) &&
1543
+ !variantObj &&
1544
+ localCreateStyles[varName]?.obj)
1300
1545
  variantObj = localCreateStyles[varName].obj;
1301
1546
  if (variantObj) {
1302
1547
  const callArgs = expr.arguments;
@@ -1407,7 +1652,11 @@ async function loader(source) {
1407
1652
  hash = mergedVariantsTable[varName];
1408
1653
  if (hash && scannedTables.variantsObjectTable[hash])
1409
1654
  variantObj = scannedTables.variantsObjectTable[hash];
1410
- if (!variantObj && localCreateStyles[varName]?.obj)
1655
+ if (!isVisibleReference(expr))
1656
+ variantObj = undefined;
1657
+ if (isVisibleReference(expr) &&
1658
+ !variantObj &&
1659
+ localCreateStyles[varName]?.obj)
1411
1660
  variantObj = localCreateStyles[varName].obj;
1412
1661
  if (variantObj) {
1413
1662
  Object.entries(variantObj).forEach(([groupName, groupVariants]) => {
@@ -1437,7 +1686,9 @@ async function loader(source) {
1437
1686
  utils_1.t.isIdentifier(expr.object) &&
1438
1687
  expr.property.type === 'Computed') {
1439
1688
  const varName = expr.object.value;
1440
- const styleObj = resolveCreateObject(varName);
1689
+ const styleObj = isVisibleReference(expr)
1690
+ ? resolveCreateObject(varName)
1691
+ : null;
1441
1692
  if (styleObj) {
1442
1693
  const dynExpr = expr.property.expression;
1443
1694
  const dynSource = getSource(dynExpr);
@@ -1766,6 +2017,8 @@ async function loader(source) {
1766
2017
  });
1767
2018
  },
1768
2019
  MemberExpression({ node }) {
2020
+ if (!isVisibleReference(node))
2021
+ return;
1769
2022
  if (utils_1.t.isIdentifier(node.object) &&
1770
2023
  (utils_1.t.isIdentifier(node.property) || node.property.type === 'Computed')) {
1771
2024
  const varName = node.object.value;
@@ -1952,50 +2205,61 @@ async function loader(source) {
1952
2205
  }
1953
2206
  }
1954
2207
  if (compKey) {
2208
+ if (node.value?.type === 'JSXExpressionContainer')
2209
+ assertNoStyleArraySpread(node.value.expression);
1955
2210
  const list = scannedTables.componentPropsTable?.[compKey]?.[attrName];
1956
2211
  if (list &&
1957
2212
  node.value &&
1958
2213
  node.value.type === 'JSXExpressionContainer') {
1959
2214
  const expr = node.value.expression;
1960
- const carrierFor = (subNode) => {
2215
+ const carrierFor = (subNode, calls) => {
1961
2216
  const vars = [];
1962
2217
  let unresolved = false;
1963
- (0, utils_1.traverse)(subNode, {
1964
- CallExpression({ node: call }) {
1965
- if (!isStyleFunctionCall(call))
1966
- return;
1967
- const resolved = resolveDynamicCall(call, true);
1968
- if (!resolved) {
1969
- unresolved = true;
1970
- return;
1971
- }
1972
- vars.push(...resolved.vars);
1973
- },
1974
- });
2218
+ for (const expression of calls ?? [subNode])
2219
+ (0, utils_1.traverse)(expression, {
2220
+ CallExpression({ node: call }) {
2221
+ if (!isStyleFunctionCall(call))
2222
+ return;
2223
+ const resolved = resolveDynamicCall(call, true);
2224
+ if (!resolved) {
2225
+ unresolved = true;
2226
+ return;
2227
+ }
2228
+ vars.push(...resolved.vars);
2229
+ },
2230
+ });
1975
2231
  if (unresolved)
1976
2232
  return null;
1977
2233
  return `{ ${foldDynamicVars(vars).join(', ')} }`;
1978
2234
  };
1979
2235
  const replaceWithKey = (subNode) => {
1980
- const entry = list.find((x) => x.spanStart === subNode.span.start &&
1981
- x.filePath === resourcePath);
1982
- if (entry) {
1983
- let content = JSON.stringify(entry.key);
2236
+ const entries = list.filter((entry) => entry.spanStart === subNode.span.start &&
2237
+ entry.filePath === resourcePath);
2238
+ if (!entries.length)
2239
+ return false;
2240
+ let content = '""';
2241
+ for (const entry of [...entries].reverse()) {
2242
+ let value = JSON.stringify(entry.key);
1984
2243
  if (entry.hasVars) {
1985
- const carrier = carrierFor(subNode);
2244
+ const carrier = carrierFor(subNode, entry.dynamicCalls);
1986
2245
  if (!carrier)
1987
2246
  return false;
1988
- content = `{ key: ${content}, vars: ${carrier} }`;
2247
+ value = `{ key: ${value}, vars: ${carrier} }`;
1989
2248
  }
1990
- replacements.push({
1991
- start: subNode.span.start - baseByteOffset,
1992
- end: subNode.span.end - baseByteOffset,
1993
- content,
1994
- });
2249
+ const condition = entry.conditions
2250
+ ?.map(({ test, truthy }) => `${truthy ? '' : '!'}(${getSource(test)})`)
2251
+ .join(' && ');
2252
+ content = condition
2253
+ ? `((${condition}) ? ${value} : ${content})`
2254
+ : value;
1995
2255
  processStyleRecords(entry.styleObj);
1996
- return true;
1997
2256
  }
1998
- return false;
2257
+ replacements.push({
2258
+ start: subNode.span.start - baseByteOffset,
2259
+ end: subNode.span.end - baseByteOffset,
2260
+ content,
2261
+ });
2262
+ return true;
1999
2263
  };
2000
2264
  (0, utils_1.traverse)(expr, {
2001
2265
  MemberExpression({ node: subNode }) {
@@ -2023,8 +2287,12 @@ async function loader(source) {
2023
2287
  const expr = node.value.expression;
2024
2288
  const args = expr.type === 'ArrayExpression'
2025
2289
  ? expr.elements
2026
- .filter((el) => el !== undefined)
2027
- .map((el) => ({ expression: el.expression }))
2290
+ .filter((el) => el != null)
2291
+ .map((el) => {
2292
+ if (el.spread)
2293
+ throwCompilationError(spreadStyleMessage(getSource(el.expression)), el.expression);
2294
+ return { expression: el.expression };
2295
+ })
2028
2296
  : [{ expression: expr }];
2029
2297
  const dynamicClassParts = [];
2030
2298
  const existingStyleParts = [];
@@ -2052,13 +2320,7 @@ async function loader(source) {
2052
2320
  existingClassExpr = JSON.stringify(classNameAttr.value.value);
2053
2321
  }
2054
2322
  else if (classNameAttr.value?.type === 'JSXExpressionContainer') {
2055
- const start = classNameAttr.value.expression.span.start -
2056
- baseByteOffset;
2057
- const end = classNameAttr.value.expression.span.end -
2058
- baseByteOffset;
2059
- existingClassExpr = `(${sourceBuffer
2060
- .subarray(start, end)
2061
- .toString('utf-8')})`;
2323
+ existingClassExpr = `(${deferSource(classNameAttr.value.expression)})`;
2062
2324
  }
2063
2325
  }
2064
2326
  const styleAttrExisting = attributes.find((attr) => attr.type === 'JSXAttribute' &&
@@ -2073,22 +2335,19 @@ async function loader(source) {
2073
2335
  });
2074
2336
  if (styleAttrExisting.value?.type === 'JSXExpressionContainer') {
2075
2337
  const innerExpr = styleAttrExisting.value?.expression;
2076
- const start = innerExpr.span.start - baseByteOffset;
2077
- const end = innerExpr.span.end - baseByteOffset;
2078
- const innerSource = sourceBuffer
2079
- .subarray(start, end)
2080
- .toString('utf-8');
2081
2338
  if (innerExpr.type === 'ObjectExpression') {
2082
- const stripped = innerSource.slice(1, -1).trim();
2083
- if (stripped)
2084
- existingStyleParts.push(stripped);
2339
+ if (innerExpr.properties.length > 0)
2340
+ existingStyleParts.push(deferSource(innerExpr, true));
2085
2341
  }
2086
2342
  else {
2087
- existingStyleExpr = `...(${innerSource})`;
2343
+ existingStyleExpr = `...(${deferSource(innerExpr)})`;
2088
2344
  }
2089
2345
  }
2090
2346
  }
2091
2347
  const { classParts, isOptimizable, baseStyle, dynamicVars, propVarSpreads, } = buildClassParts(args, dynamicClassParts, existingClassExpr, true);
2348
+ if (!isOptimizable) {
2349
+ throwCompilationError(`Plumeria: Dynamic or unresolvable style object "${getSource(expr)}" is not supported.`, expr);
2350
+ }
2092
2351
  const styleParts = [
2093
2352
  ...existingStyleParts,
2094
2353
  ...foldDynamicVars(dynamicVars),
@@ -2227,6 +2486,22 @@ async function loader(source) {
2227
2486
  `so it cannot be passed through another prop or read as a value.`, call);
2228
2487
  }
2229
2488
  });
2489
+ for (const deferred of deferredSources) {
2490
+ let cursor = deferred.start;
2491
+ const pieces = [];
2492
+ for (const replacement of [...replacements].sort((a, b) => a.start - b.start || b.end - a.end)) {
2493
+ if (replacement.start < cursor || replacement.end > deferred.end)
2494
+ continue;
2495
+ pieces.push(sourceBuffer.subarray(cursor, replacement.start).toString('utf-8'), replacement.content);
2496
+ cursor = replacement.end;
2497
+ }
2498
+ pieces.push(sourceBuffer.subarray(cursor, deferred.end).toString('utf-8'));
2499
+ let content = pieces.join('');
2500
+ if (deferred.stripObject)
2501
+ content = content.slice(1, -1).trim();
2502
+ for (const replacement of replacements)
2503
+ replacement.content = replacement.content.replaceAll(deferred.token, content);
2504
+ }
2230
2505
  const buffer = Buffer.from(source);
2231
2506
  let offset = 0;
2232
2507
  const parts = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeria/turbopack-loader",
3
- "version": "18.4.2",
3
+ "version": "18.5.1",
4
4
  "description": "Plumeria Turbopack-loader",
5
5
  "author": "Refirst 11",
6
6
  "license": "MIT",
@@ -29,8 +29,8 @@
29
29
  "zero-virtual.css"
30
30
  ],
31
31
  "dependencies": {
32
- "@plumeria/compiler": "^18.4.2",
33
- "@plumeria/utils": "^18.4.2"
32
+ "@plumeria/compiler": "^18.5.1",
33
+ "@plumeria/utils": "^18.5.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@swc/core": "1.15.47",