From ffd291fe4f06645958fc181c171a5f942ad23f43 Mon Sep 17 00:00:00 2001 From: Makin Date: Wed, 18 Jun 2025 18:55:16 +0200 Subject: add faster case for add(...args) --- src/html.js | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/html.js b/src/html.js index 3b399079..71b6f4d5 100644 --- a/src/html.js +++ b/src/html.js @@ -1136,6 +1136,34 @@ export class Attributes { } add(...args) { + // Very common case: add({class: 'foo', id: 'bar'})ยก + // The argument is a plain object (no Template, no Attributes, + // no blessAttributes symbol). We can skip the expensive + // isAttributesAdditionSinglet() validation and flatten/array handling. + if ( + args.length === 1 && + args[0] && + typeof args[0] === 'object' && + !Array.isArray(args[0]) && + !(args[0] instanceof Attributes) && + !(args[0] instanceof Template) && + !Object.hasOwn(args[0], blessAttributes) + ) { + const obj = args[0]; + + // Preserve existing merge semantics by funnelling each key through + // the internal #addOneAttribute helper (handles class/style union, + // unique merging, etc.) but avoid *per-object* validation overhead. + for (const [key, val] of Object.entries(obj)) { + this.#addOneAttribute(key, val); + } + + // Match the original return style (list of results) so callers that + // inspect the return continue to work. + return obj; + } + + // Fall back to the original slow-but-thorough implementation switch (args.length) { case 1: isAttributesAdditionSinglet(args[0]); @@ -1147,10 +1175,11 @@ export class Attributes { default: throw new Error( - `Expected array or object, or attribute and value`); + 'Expected array or object, or attribute and value'); } } + with(...args) { const clone = this.clone(); clone.add(...args); -- cgit 1.3.0-6-gf8a5