diff --git a/packages/babel-plugin-jsx-dom-expressions/src/dom/element.js b/packages/babel-plugin-jsx-dom-expressions/src/dom/element.js index 26153bd5..866d7387 100644 --- a/packages/babel-plugin-jsx-dom-expressions/src/dom/element.js +++ b/packages/babel-plugin-jsx-dom-expressions/src/dom/element.js @@ -297,6 +297,31 @@ function transformAttributes(path, results) { ); //NOTE: can't be checked at compile time so add to compiled output hasHydratableEvent = true; + } else { + /** + * Spreads already de-duplicate attributes. + * + * This handles the case when attributes are duplicated without the presence of a spread. Such: + * `
;` + */ + const seenAttributes = {}; + const duplicates = []; + path + .get("openingElement") + .get("attributes") + .forEach(attr => { + const key = t.isJSXNamespacedName(attr.node.name) + ? `${attr.node.name.namespace.name}:${attr.node.name.name.name}` + : attr.node.name.name; + + if (!key.startsWith("use:") && key !== "ref" && seenAttributes[key]) { + duplicates.push(seenAttributes[key]); + } + seenAttributes[key] = attr; + }); + for (const duplicate of duplicates) { + duplicate.remove(); + } } /** @@ -1171,12 +1196,7 @@ function processSpreads(path, attributes, { elem, isSVG, hasChildren, wrapCondit : node.argument; spreadArgs.push(isStatic ? t.objectExpression([t.spreadElement(s)]) : s); - } else if ( - (firstSpread || - (t.isJSXExpressionContainer(node.value) && - isDynamic(attribute.get("value").get("expression"), { checkMember: true }))) && - canNativeSpread(key, { checkNameSpaces: true }) - ) { + } else if (key && !key.startsWith("use:") && key !== "ref") { const isContainer = t.isJSXExpressionContainer(node.value); const dynamic = isContainer && isDynamic(attribute.get("value").get("expression"), { checkMember: true }); diff --git a/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/code.js b/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/code.js index 7425e869..a8b28d3b 100644 --- a/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/code.js +++ b/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/code.js @@ -325,3 +325,5 @@ const template88 = ( {count()} ); + +const template89 = diff --git a/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/output.js b/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/output.js index 6702b7f9..fcf5c151 100644 --- a/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/output.js +++ b/packages/babel-plugin-jsx-dom-expressions/test/__dom_compatible_fixtures__/attributeExpressions/output.js @@ -11,9 +11,7 @@ import { className as _$className } from "r-dom"; import { use as _$use } from "r-dom"; import { spread as _$spread } from "r-dom"; import { mergeProps as _$mergeProps } from "r-dom"; -var _tmpl$ = /*#__PURE__*/ _$template( - `` - ), +var _tmpl$ = /*#__PURE__*/ _$template(``), _tmpl$2 = /*#__PURE__*/ _$template(`