babel-plugin-react-compiler 19.0.0-beta-e552027-20250112 → 19.0.0-beta-27714ef-20250124

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/dist/index.js CHANGED
@@ -121306,8 +121306,16 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
121306
121306
  [
121307
121307
  "map",
121308
121308
  addFunction(BUILTIN_SHAPES, [], {
121309
+ /**
121310
+ * Note `map`'s arguments are annotated as Effect.ConditionallyMutate as
121311
+ * calling `<array>.map(fn)` might invoke `fn`, which means replaying its
121312
+ * effects.
121313
+ *
121314
+ * (Note that Effect.Read / Effect.Capture on a function type means
121315
+ * potential data dependency or aliasing respectively.)
121316
+ */
121309
121317
  positionalParams: [],
121310
- restParam: "read" /* Read */,
121318
+ restParam: "mutate?" /* ConditionallyMutate */,
121311
121319
  returnType: { kind: "Object", shapeId: BuiltInArrayId },
121312
121320
  calleeEffect: "mutate?" /* ConditionallyMutate */,
121313
121321
  returnValueKind: "mutable" /* Mutable */,
@@ -121318,7 +121326,7 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
121318
121326
  "flatMap",
121319
121327
  addFunction(BUILTIN_SHAPES, [], {
121320
121328
  positionalParams: [],
121321
- restParam: "read" /* Read */,
121329
+ restParam: "mutate?" /* ConditionallyMutate */,
121322
121330
  returnType: { kind: "Object", shapeId: BuiltInArrayId },
121323
121331
  calleeEffect: "mutate?" /* ConditionallyMutate */,
121324
121332
  returnValueKind: "mutable" /* Mutable */,
@@ -121329,7 +121337,7 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
121329
121337
  "filter",
121330
121338
  addFunction(BUILTIN_SHAPES, [], {
121331
121339
  positionalParams: [],
121332
- restParam: "read" /* Read */,
121340
+ restParam: "mutate?" /* ConditionallyMutate */,
121333
121341
  returnType: { kind: "Object", shapeId: BuiltInArrayId },
121334
121342
  calleeEffect: "mutate?" /* ConditionallyMutate */,
121335
121343
  returnValueKind: "mutable" /* Mutable */,
@@ -125468,6 +125476,48 @@ var TYPED_GLOBALS = [
125468
125476
  ]
125469
125477
  ])
125470
125478
  ],
125479
+ [
125480
+ "performance",
125481
+ addObject(DEFAULT_SHAPES, "performance", [
125482
+ // Static methods (TODO)
125483
+ [
125484
+ "now",
125485
+ // Date.now()
125486
+ addFunction(DEFAULT_SHAPES, [], {
125487
+ positionalParams: [],
125488
+ restParam: "read" /* Read */,
125489
+ returnType: { kind: "Poly" },
125490
+ // TODO: could be Primitive, but that would change existing compilation
125491
+ calleeEffect: "read" /* Read */,
125492
+ returnValueKind: "mutable" /* Mutable */,
125493
+ // same here
125494
+ impure: true,
125495
+ canonicalName: "performance.now"
125496
+ })
125497
+ ]
125498
+ ])
125499
+ ],
125500
+ [
125501
+ "Date",
125502
+ addObject(DEFAULT_SHAPES, "Date", [
125503
+ // Static methods (TODO)
125504
+ [
125505
+ "now",
125506
+ // Date.now()
125507
+ addFunction(DEFAULT_SHAPES, [], {
125508
+ positionalParams: [],
125509
+ restParam: "read" /* Read */,
125510
+ returnType: { kind: "Poly" },
125511
+ // TODO: could be Primitive, but that would change existing compilation
125512
+ calleeEffect: "read" /* Read */,
125513
+ returnValueKind: "mutable" /* Mutable */,
125514
+ // same here
125515
+ impure: true,
125516
+ canonicalName: "Date.now"
125517
+ })
125518
+ ]
125519
+ ])
125520
+ ],
125471
125521
  [
125472
125522
  "Math",
125473
125523
  addObject(DEFAULT_SHAPES, "Math", [
@@ -125535,6 +125585,20 @@ var TYPED_GLOBALS = [
125535
125585
  calleeEffect: "read" /* Read */,
125536
125586
  returnValueKind: "primitive" /* Primitive */
125537
125587
  })
125588
+ ],
125589
+ [
125590
+ "random",
125591
+ addFunction(DEFAULT_SHAPES, [], {
125592
+ positionalParams: [],
125593
+ restParam: "read" /* Read */,
125594
+ returnType: { kind: "Poly" },
125595
+ // TODO: could be Primitive, but that would change existing compilation
125596
+ calleeEffect: "read" /* Read */,
125597
+ returnValueKind: "mutable" /* Mutable */,
125598
+ // same here
125599
+ impure: true,
125600
+ canonicalName: "Math.random"
125601
+ })
125538
125602
  ]
125539
125603
  ])
125540
125604
  ],
@@ -126073,7 +126137,9 @@ var FunctionTypeSchema = z.object({
126073
126137
  returnType: z.lazy(() => TypeSchema),
126074
126138
  returnValueKind: ValueKindSchema,
126075
126139
  noAlias: z.boolean().nullable().optional(),
126076
- mutableOnlyIfOperandsAreMutable: z.boolean().nullable().optional()
126140
+ mutableOnlyIfOperandsAreMutable: z.boolean().nullable().optional(),
126141
+ impure: z.boolean().nullable().optional(),
126142
+ canonicalName: z.string().nullable().optional()
126077
126143
  });
126078
126144
  var HookTypeSchema = z.object({
126079
126145
  kind: z.literal("hook"),
@@ -126346,6 +126412,10 @@ var EnvironmentConfigSchema = z.object({
126346
126412
  */
126347
126413
  validateNoCapitalizedCalls: z.nullable(z.array(z.string())).default(null),
126348
126414
  validateBlocklistedImports: z.nullable(z.array(z.string())).default(null),
126415
+ /**
126416
+ * Validate against impure functions called during render
126417
+ */
126418
+ validateNoImpureFunctionsInRender: z.boolean().default(false),
126349
126419
  /*
126350
126420
  * When enabled, the compiler assumes that hooks follow the Rules of React:
126351
126421
  * - Hooks may memoize computation based on any of their parameters, thus
@@ -133682,7 +133752,7 @@ function codegenInstructionValue(cx, instrValue) {
133682
133752
  }
133683
133753
  return value;
133684
133754
  }
133685
- var STRING_REQUIRES_EXPR_CONTAINER_PATTERN = /[\u{0000}-\u{001F}\u{007F}\u{0080}-\u{FFFF}]|"/u;
133755
+ var STRING_REQUIRES_EXPR_CONTAINER_PATTERN = /[\u{0000}-\u{001F}\u{007F}\u{0080}-\u{FFFF}]|"|\\/u;
133686
133756
  function codegenJsxAttribute(cx, attribute) {
133687
133757
  switch (attribute.kind) {
133688
133758
  case "JsxAttribute": {
@@ -133727,7 +133797,7 @@ function codegenJsxAttribute(cx, attribute) {
133727
133797
  }
133728
133798
  }
133729
133799
  }
133730
- var JSX_TEXT_CHILD_REQUIRES_EXPR_CONTAINER_PATTERN = /[<>&]/;
133800
+ var JSX_TEXT_CHILD_REQUIRES_EXPR_CONTAINER_PATTERN = /[<>&{}]/;
133731
133801
  function codegenJsxElement(cx, place) {
133732
133802
  const value = codegenPlace(cx, place);
133733
133803
  switch (value.type) {
@@ -134923,11 +134993,15 @@ function inferOperandEffect(state, place) {
134923
134993
  if (isRefOrRefValue(place.identifier)) {
134924
134994
  break;
134925
134995
  } else if (value.kind === "context" /* Context */) {
134996
+ CompilerError.invariant(value.context.size > 0, {
134997
+ reason: "[InferFunctionEffects] Expected Context-kind value's capture list to be non-empty.",
134998
+ loc: place.loc
134999
+ });
134926
135000
  return {
134927
135001
  kind: "ContextMutation",
134928
135002
  loc: place.loc,
134929
135003
  effect: place.effect,
134930
- places: value.context.size === 0 ? /* @__PURE__ */ new Set([place]) : value.context
135004
+ places: value.context
134931
135005
  };
134932
135006
  } else if (value.kind !== "mutable" /* Mutable */ && // We ignore mutations of primitives since this is not a React-specific problem
134933
135007
  value.kind !== "primitive" /* Primitive */) {
@@ -135682,10 +135756,11 @@ function inferBlock(env, state, block, functionEffects) {
135682
135756
  break;
135683
135757
  }
135684
135758
  case "ArrayExpression": {
135685
- const valueKind = hasContextRefOperand(state, instrValue) ? {
135759
+ const contextRefOperands = getContextRefOperand(state, instrValue);
135760
+ const valueKind = contextRefOperands.length > 0 ? {
135686
135761
  kind: "context" /* Context */,
135687
135762
  reason: /* @__PURE__ */ new Set(["other" /* Other */]),
135688
- context: /* @__PURE__ */ new Set()
135763
+ context: new Set(contextRefOperands)
135689
135764
  } : {
135690
135765
  kind: "mutable" /* Mutable */,
135691
135766
  reason: /* @__PURE__ */ new Set(["other" /* Other */]),
@@ -135726,10 +135801,11 @@ function inferBlock(env, state, block, functionEffects) {
135726
135801
  break;
135727
135802
  }
135728
135803
  case "ObjectExpression": {
135729
- const valueKind = hasContextRefOperand(state, instrValue) ? {
135804
+ const contextRefOperands = getContextRefOperand(state, instrValue);
135805
+ const valueKind = contextRefOperands.length > 0 ? {
135730
135806
  kind: "context" /* Context */,
135731
135807
  reason: /* @__PURE__ */ new Set(["other" /* Other */]),
135732
- context: /* @__PURE__ */ new Set()
135808
+ context: new Set(contextRefOperands)
135733
135809
  } : {
135734
135810
  kind: "mutable" /* Mutable */,
135735
135811
  reason: /* @__PURE__ */ new Set(["other" /* Other */]),
@@ -136319,11 +136395,17 @@ function inferBlock(env, state, block, functionEffects) {
136319
136395
  }
136320
136396
  case "LoadLocal": {
136321
136397
  const lvalue = instr.lvalue;
136322
- const effect = state.isDefined(lvalue) && state.kind(lvalue).kind === "context" /* Context */ ? "mutate?" /* ConditionallyMutate */ : "capture" /* Capture */;
136398
+ CompilerError.invariant(
136399
+ !(state.isDefined(lvalue) && state.kind(lvalue).kind === "context" /* Context */),
136400
+ {
136401
+ reason: "[InferReferenceEffects] Unexpected LoadLocal with context kind",
136402
+ loc: lvalue.loc
136403
+ }
136404
+ );
136323
136405
  state.referenceAndRecordEffects(
136324
136406
  freezeActions,
136325
136407
  instrValue.place,
136326
- effect,
136408
+ "capture" /* Capture */,
136327
136409
  "other" /* Other */
136328
136410
  );
136329
136411
  lvalue.effect = "mutate?" /* ConditionallyMutate */;
@@ -136577,13 +136659,14 @@ function inferBlock(env, state, block, functionEffects) {
136577
136659
  ({ values, reason }) => state.freezeValues(values, reason)
136578
136660
  );
136579
136661
  }
136580
- function hasContextRefOperand(state, instrValue) {
136662
+ function getContextRefOperand(state, instrValue) {
136663
+ const result = [];
136581
136664
  for (const place of eachInstructionValueOperand(instrValue)) {
136582
136665
  if (state.isDefined(place) && state.kind(place).kind === "context" /* Context */) {
136583
- return true;
136666
+ result.push(place);
136584
136667
  }
136585
136668
  }
136586
- return false;
136669
+ return result;
136587
136670
  }
136588
136671
  function getFunctionCallSignature(env, type) {
136589
136672
  if (type.kind !== "Function") {
@@ -144552,6 +144635,35 @@ function rewriteInstructions(rewriteInstrs, instructions) {
144552
144635
  return instructions;
144553
144636
  }
144554
144637
 
144638
+ // src/Validation/ValiateNoImpureFunctionsInRender.ts
144639
+ function validateNoImpureFunctionsInRender(fn) {
144640
+ const errors = new CompilerError();
144641
+ for (const [, block] of fn.body.blocks) {
144642
+ for (const instr of block.instructions) {
144643
+ const value = instr.value;
144644
+ if (value.kind === "MethodCall" || value.kind == "CallExpression") {
144645
+ const callee = value.kind === "MethodCall" ? value.property : value.callee;
144646
+ const signature = getFunctionCallSignature(
144647
+ fn.env,
144648
+ callee.identifier.type
144649
+ );
144650
+ if (signature != null && signature.impure === true) {
144651
+ errors.push({
144652
+ reason: "Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)",
144653
+ description: signature.canonicalName != null ? `\`${signature.canonicalName}\` is an impure function whose results may change on every call` : null,
144654
+ severity: "InvalidReact" /* InvalidReact */,
144655
+ loc: callee.loc,
144656
+ suggestions: null
144657
+ });
144658
+ }
144659
+ }
144660
+ }
144661
+ }
144662
+ if (errors.hasErrors()) {
144663
+ throw errors;
144664
+ }
144665
+ }
144666
+
144555
144667
  // src/Entrypoint/Pipeline.ts
144556
144668
  function run(func, config, fnType, useMemoCacheIdentifier, logger, filename, code) {
144557
144669
  const contextIdentifiers = findContextIdentifiers(func);
@@ -144650,6 +144762,9 @@ function runWithEnvironment(func, env) {
144650
144762
  if (env.config.validateNoJSXInTryStatements) {
144651
144763
  validateNoJSXInTryStatement(hir);
144652
144764
  }
144765
+ if (env.config.validateNoImpureFunctionsInRender) {
144766
+ validateNoImpureFunctionsInRender(hir);
144767
+ }
144653
144768
  inferReactivePlaces(hir);
144654
144769
  log2({ kind: "hir", name: "InferReactivePlaces", value: hir });
144655
144770
  rewriteInstructionKindsBasedOnReassignment(hir);
@@ -145646,9 +145761,11 @@ function returnsNonNode(node) {
145646
145761
  }
145647
145762
  }
145648
145763
  },
145764
+ // Skip traversing all nested functions and their return statements
145649
145765
  ArrowFunctionExpression: skipNestedFunctions(node),
145650
145766
  FunctionExpression: skipNestedFunctions(node),
145651
- FunctionDeclaration: skipNestedFunctions(node)
145767
+ FunctionDeclaration: skipNestedFunctions(node),
145768
+ ObjectMethod: (node2) => node2.skip()
145652
145769
  });
145653
145770
  return !hasReturn || returnsNonNode2;
145654
145771
  }