From 12035320073a81858a83d4b9f457449569f741df Mon Sep 17 00:00:00 2001 From: nic <139033898+dicnunz@users.noreply.github.com> Date: Sat, 9 May 2026 02:36:59 -0400 Subject: [PATCH] Fix class property refs for transformed builtins --- ...77-map-class-property-transform-runtime.js | 16 ++++++ .../src/transformVisitors.js | 50 +++++++++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/bugs/177-map-class-property-transform-runtime.js diff --git a/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/bugs/177-map-class-property-transform-runtime.js b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/bugs/177-map-class-property-transform-runtime.js new file mode 100644 index 0000000..ace7280 --- /dev/null +++ b/packages/babel-plugin-flow-runtime/src/__tests__/__fixtures__/bugs/177-map-class-property-transform-runtime.js @@ -0,0 +1,16 @@ +// @flow + +export const input = ` + class Foo { + bar: Map = new Map(); + } +`; + +export const expected = ` + import t from "flow-runtime"; + + class Foo { + @t.decorate(t.ref(Map, t.string(), t.any())) + bar = new Map(); + } +`; diff --git a/packages/babel-plugin-flow-runtime/src/transformVisitors.js b/packages/babel-plugin-flow-runtime/src/transformVisitors.js index e88d0f7..2654ec7 100644 --- a/packages/babel-plugin-flow-runtime/src/transformVisitors.js +++ b/packages/babel-plugin-flow-runtime/src/transformVisitors.js @@ -11,6 +11,12 @@ import {ok as invariant} from 'assert'; import type {Node, NodePath} from '@babel/traverse'; const flowConfig = loadFlowConfig(); +const VALUE_REFERENCE_TYPE_CONSTRUCTORS = new Set([ + 'Date', + 'Map', + 'Promise', + 'Set' +]); export default function transformVisitors (context: ConversionContext): Object { const shouldCheck = context.shouldAssert || context.shouldWarn; @@ -813,7 +819,7 @@ export default function transformVisitors (context: ConversionContext): Object { null, [], t.blockStatement([ - t.returnStatement(convert(context, typeAnnotation)) + t.returnStatement(convertClassPropertyDecoratorType(context, typeAnnotation)) ]) ) ]; @@ -827,12 +833,12 @@ export default function transformVisitors (context: ConversionContext): Object { } else if (context.shouldWarn) { decorator = t.decorator( - context.call('decorate', convert(context, typeAnnotation), t.booleanLiteral(false)) + context.call('decorate', convertClassPropertyDecoratorType(context, typeAnnotation), t.booleanLiteral(false)) ); } else { decorator = t.decorator( - context.call('decorate', convert(context, typeAnnotation)) + context.call('decorate', convertClassPropertyDecoratorType(context, typeAnnotation)) ); } if (!path.has('decorators')) { @@ -843,6 +849,44 @@ export default function transformVisitors (context: ConversionContext): Object { }; } +function convertClassPropertyDecoratorType (context: ConversionContext, path: NodePath): Node { + const converted = convert(context, path); + rewriteValueReferenceTypeConstructors(context, converted); + return converted; +} + +function rewriteValueReferenceTypeConstructors (context: ConversionContext, node: any) { + if (!node || typeof node !== 'object') { + return; + } + + if (Array.isArray(node)) { + for (const item of node) { + rewriteValueReferenceTypeConstructors(context, item); + } + return; + } + + if ( + t.isCallExpression(node) && + t.isMemberExpression(node.callee) && + !node.callee.computed && + t.isIdentifier(node.callee.object, {name: context.libraryId}) && + t.isIdentifier(node.callee.property, {name: 'ref'}) && + t.isStringLiteral(node.arguments[0]) && + VALUE_REFERENCE_TYPE_CONSTRUCTORS.has(node.arguments[0].value) + ) { + node.arguments[0] = t.identifier(node.arguments[0].value); + } + + for (const key of Object.keys(node)) { + if (key === 'loc' || key === 'start' || key === 'end') { + continue; + } + rewriteValueReferenceTypeConstructors(context, node[key]); + } +} + function isReactComponentClass (path: NodePath): boolean { if (path.isIdentifier()) { return path.node.name === path.scope.getData('reactComponentClass')