: attribute "data-foo" has different values, expected "client" but found "server"'
+ );
+ expect(consoleCalls.error[1][0].message).toContain('Hydration completed with errors.');
+ },
+};
diff --git a/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.html b/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.html
new file mode 100644
index 0000000000..1a3f98cdd6
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.js b/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.js
new file mode 100644
index 0000000000..869ac698f9
--- /dev/null
+++ b/packages/@lwc/integration-karma/test-hydration/mismatches/attrs-expression/x/main/main.js
@@ -0,0 +1,5 @@
+import { LightningElement, api } from 'lwc';
+
+export default class extends LightningElement {
+ @api foo;
+}
diff --git a/packages/@lwc/integration-karma/test/static-content/index.spec.js b/packages/@lwc/integration-karma/test/static-content/index.spec.js
index 043b1d010d..91967626c4 100644
--- a/packages/@lwc/integration-karma/test/static-content/index.spec.js
+++ b/packages/@lwc/integration-karma/test/static-content/index.spec.js
@@ -16,6 +16,8 @@ import ListenerStaticWithUpdates from 'x/listenerStaticWithUpdates';
import DeepListener from 'x/deepListener';
import Comments from 'x/comments';
import PreserveComments from 'x/preserveComments';
+import AttributeExpression from 'x/attributeExpression';
+import DeepAttributeExpression from 'x/DeepAttributeExpression';
if (!process.env.NATIVE_SHADOW) {
describe('Mixed mode for static content', () => {
@@ -432,3 +434,51 @@ describe('static parts applies to comments correctly', () => {
expect(refs.bar).toBe(bar);
});
});
+
+describe('static optimization with attributes', () => {
+ it('applies expressions on mount', async () => {
+ const elm = createElement('x-attribute-expression', { is: AttributeExpression });
+ document.body.appendChild(elm);
+ await Promise.resolve();
+
+ const nodes = extractDataIds(elm);
+ expect(nodes['loaded-on-mount'].getAttribute('data-mount')).toEqual('loaded on mount');
+ expect(nodes['loaded-on-mount-nested'].getAttribute('data-mount')).toEqual(
+ 'loaded on mount'
+ );
+ });
+
+ it('updates expressions when data changes', async () => {
+ const elm = createElement('x-attribute-expression', { is: AttributeExpression });
+ document.body.appendChild(elm);
+ await Promise.resolve();
+
+ const nodes = extractDataIds(elm);
+ expect(nodes['loaded-on-update'].getAttribute('data-update')).toBe(null);
+ expect(nodes['loaded-on-update-nested'].getAttribute('data-update')).toBe(null);
+
+ elm.update = 'expression updated';
+ await Promise.resolve();
+
+ expect(nodes['loaded-on-update'].getAttribute('data-update')).toEqual('expression updated');
+ expect(nodes['loaded-on-update-nested'].getAttribute('data-update')).toEqual(
+ 'expression updated'
+ );
+ });
+
+ it('applies expression from deeply nested data structure', async () => {
+ const elm = createElement('x-deep-attribute-expression', { is: DeepAttributeExpression });
+ document.body.appendChild(elm);
+ await Promise.resolve();
+
+ const nodes = extractDataIds(elm);
+ expect(nodes['deep1'].getAttribute('data-dynamic')).toEqual('1');
+ expect(nodes['deep1nested'].getAttribute('data-dynamic')).toEqual('1');
+ expect(nodes['deep2'].getAttribute('data-dynamic')).toEqual('2');
+ expect(nodes['deep2nested'].getAttribute('data-dynamic')).toEqual('2');
+ expect(nodes['deep3'].getAttribute('data-dynamic')).toEqual('3');
+ expect(nodes['deep3nested'].getAttribute('data-dynamic')).toEqual('3');
+ expect(nodes['deep4'].getAttribute('data-dynamic')).toEqual('4');
+ expect(nodes['deep4nested'].getAttribute('data-dynamic')).toEqual('4');
+ });
+});
diff --git a/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.html b/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.html
new file mode 100644
index 0000000000..adfe84ff8d
--- /dev/null
+++ b/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.js b/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.js
new file mode 100644
index 0000000000..bb65cc8824
--- /dev/null
+++ b/packages/@lwc/integration-karma/test/static-content/x/attributeExpression/attributeExpression.js
@@ -0,0 +1,8 @@
+import { LightningElement, api } from 'lwc';
+
+export default class extends LightningElement {
+ mount = 'loaded on mount';
+
+ @api
+ update;
+}
diff --git a/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.html b/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.html
new file mode 100644
index 0000000000..cbbc73643d
--- /dev/null
+++ b/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.js b/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.js
new file mode 100644
index 0000000000..30bc67f6b6
--- /dev/null
+++ b/packages/@lwc/integration-karma/test/static-content/x/deepAttributeExpression/deepAttributeExpression.js
@@ -0,0 +1,8 @@
+import { LightningElement } from 'lwc';
+
+export default class extends LightningElement {
+ one = 1;
+ un = { deux: 2 };
+ uno = { dos: { tres: 3 } };
+ ichi = { ni: { san: { shi: 4 } } };
+}
diff --git a/packages/@lwc/integration-tests/package.json b/packages/@lwc/integration-tests/package.json
index 4b06b9d9de..76ca400a82 100644
--- a/packages/@lwc/integration-tests/package.json
+++ b/packages/@lwc/integration-tests/package.json
@@ -1,7 +1,7 @@
{
"name": "@lwc/integration-tests",
"private": true,
- "version": "6.3.3",
+ "version": "6.3.4",
"scripts": {
"build": "node scripts/build.js",
"build:dev": "MODE=dev yarn build",
@@ -16,7 +16,7 @@
"sauce:prod:ci": "MODE=prod yarn build:prod && MODE=prod ../../../scripts/ci/retry.sh wdio ./scripts/wdio.sauce.conf.js"
},
"devDependencies": {
- "@lwc/rollup-plugin": "6.3.3",
+ "@lwc/rollup-plugin": "6.3.4",
"@wdio/cli": "^8.33.1",
"@wdio/local-runner": "^8.33.1",
"@wdio/mocha-framework": "^8.33.1",
@@ -25,7 +25,7 @@
"@wdio/static-server-service": "^8.32.4",
"deepmerge": "^4.3.0",
"dotenv": "^16.4.5",
- "lwc": "6.3.3",
+ "lwc": "6.3.4",
"minimist": "^1.2.8",
"webdriverio": "^8.33.1"
}
diff --git a/packages/@lwc/module-resolver/package.json b/packages/@lwc/module-resolver/package.json
index 3f11350c2e..b1572c15f4 100644
--- a/packages/@lwc/module-resolver/package.json
+++ b/packages/@lwc/module-resolver/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/module-resolver",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Resolves paths for LWC components",
"keywords": [
"lwc"
diff --git a/packages/@lwc/perf-benchmarks-components/package.json b/packages/@lwc/perf-benchmarks-components/package.json
index 9dd5b21221..3b1df13a58 100644
--- a/packages/@lwc/perf-benchmarks-components/package.json
+++ b/packages/@lwc/perf-benchmarks-components/package.json
@@ -1,12 +1,12 @@
{
"name": "@lwc/perf-benchmarks-components",
- "version": "6.3.3",
+ "version": "6.3.4",
"private": true,
"scripts": {
"build": "rm -fr dist && rollup -c ./rollup.config.mjs"
},
"devDependencies": {
- "@lwc/rollup-plugin": "6.3.3"
+ "@lwc/rollup-plugin": "6.3.4"
},
"nx": {
"targets": {
diff --git a/packages/@lwc/perf-benchmarks/package.json b/packages/@lwc/perf-benchmarks/package.json
index 90c143cdab..0d59447737 100644
--- a/packages/@lwc/perf-benchmarks/package.json
+++ b/packages/@lwc/perf-benchmarks/package.json
@@ -1,6 +1,6 @@
{
"name": "@lwc/perf-benchmarks",
- "version": "6.3.3",
+ "version": "6.3.4",
"private": true,
"scripts": {
"build": "rm -fr dist && rollup -c ./rollup.config.mjs && node scripts/build.js && ./scripts/fix-deps.sh",
@@ -17,10 +17,10 @@
"Also note that we use legacy versions of rollup-plugin-node-resolve and rollup-plugin-commonjs because Best uses an old version of Rollup."
],
"dependencies": {
- "@lwc/engine-dom": "6.3.3",
- "@lwc/engine-server": "6.3.3",
- "@lwc/perf-benchmarks-components": "6.3.3",
- "@lwc/synthetic-shadow": "6.3.3"
+ "@lwc/engine-dom": "6.3.4",
+ "@lwc/engine-server": "6.3.4",
+ "@lwc/perf-benchmarks-components": "6.3.4",
+ "@lwc/synthetic-shadow": "6.3.4"
},
"devDependencies": {
"@best/cli": "^11.0.0",
diff --git a/packages/@lwc/rollup-plugin/package.json b/packages/@lwc/rollup-plugin/package.json
index ecb9c44415..0559d1e1dc 100644
--- a/packages/@lwc/rollup-plugin/package.json
+++ b/packages/@lwc/rollup-plugin/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/rollup-plugin",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Rollup plugin to compile LWC",
"keywords": [
"lwc"
@@ -42,12 +42,12 @@
}
},
"dependencies": {
- "@lwc/compiler": "6.3.3",
- "@lwc/module-resolver": "6.3.3",
+ "@lwc/compiler": "6.3.4",
+ "@lwc/module-resolver": "6.3.4",
"@rollup/pluginutils": "~5.1.0"
},
"devDependencies": {
- "@lwc/errors": "6.3.3"
+ "@lwc/errors": "6.3.4"
},
"peerDependencies": {
"rollup": "^1.2.0||^2.0.0||^3.0.0||^4.0.0"
diff --git a/packages/@lwc/shared/package.json b/packages/@lwc/shared/package.json
index 48d005c44f..2fb45bfdc3 100644
--- a/packages/@lwc/shared/package.json
+++ b/packages/@lwc/shared/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/shared",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Utilities and methods that are shared across packages",
"keywords": [
"lwc"
diff --git a/packages/@lwc/shared/src/index.ts b/packages/@lwc/shared/src/index.ts
index b5e7e918fd..091638e8c2 100644
--- a/packages/@lwc/shared/src/index.ts
+++ b/packages/@lwc/shared/src/index.ts
@@ -15,5 +15,6 @@ export * from './html-attributes';
export * from './html-escape';
export * from './namespaces';
export * from './meta';
+export * from './static-part-tokens';
export { assert };
diff --git a/packages/@lwc/shared/src/static-part-tokens.ts b/packages/@lwc/shared/src/static-part-tokens.ts
new file mode 100644
index 0000000000..925c545052
--- /dev/null
+++ b/packages/@lwc/shared/src/static-part-tokens.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2024, salesforce.com, inc.
+ * All rights reserved.
+ * SPDX-License-Identifier: MIT
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
+ */
+
+export const enum STATIC_PART_TOKEN_ID {
+ ATTRIBUTE = 'a',
+ CLASS = 'c',
+ STYLE = 's',
+ TEXT = 't',
+}
diff --git a/packages/@lwc/signals/package.json b/packages/@lwc/signals/package.json
index 1f2ec78cd7..5fc0d00e8e 100644
--- a/packages/@lwc/signals/package.json
+++ b/packages/@lwc/signals/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/signals",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Provides the interface to interact with reactivity from outside the framework",
"keywords": [
"lwc"
diff --git a/packages/@lwc/style-compiler/package.json b/packages/@lwc/style-compiler/package.json
index 5d7b741064..b7e9823ad7 100644
--- a/packages/@lwc/style-compiler/package.json
+++ b/packages/@lwc/style-compiler/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/style-compiler",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Transform style sheet to be consumed by the LWC engine",
"keywords": [
"lwc"
@@ -42,7 +42,7 @@
}
},
"dependencies": {
- "@lwc/shared": "6.3.3",
+ "@lwc/shared": "6.3.4",
"postcss": "~8.4.35",
"postcss-selector-parser": "~6.0.15",
"postcss-value-parser": "~4.2.0"
diff --git a/packages/@lwc/synthetic-shadow/package.json b/packages/@lwc/synthetic-shadow/package.json
index 585b08ecac..bf12c9f20d 100644
--- a/packages/@lwc/synthetic-shadow/package.json
+++ b/packages/@lwc/synthetic-shadow/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/synthetic-shadow",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Synthetic Shadow Root for LWC",
"keywords": [
"lwc"
@@ -42,8 +42,8 @@
}
},
"devDependencies": {
- "@lwc/features": "6.3.3",
- "@lwc/shared": "6.3.3"
+ "@lwc/features": "6.3.4",
+ "@lwc/shared": "6.3.4"
},
"lwc": {
"modules": [
diff --git a/packages/@lwc/template-compiler/package.json b/packages/@lwc/template-compiler/package.json
index 817a9720d8..6efc1893b3 100644
--- a/packages/@lwc/template-compiler/package.json
+++ b/packages/@lwc/template-compiler/package.json
@@ -4,7 +4,7 @@
"You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
],
"name": "@lwc/template-compiler",
- "version": "6.3.3",
+ "version": "6.3.4",
"description": "Template compiler package",
"keywords": [
"lwc"
@@ -42,8 +42,8 @@
}
},
"dependencies": {
- "@lwc/errors": "6.3.3",
- "@lwc/shared": "6.3.3",
+ "@lwc/errors": "6.3.4",
+ "@lwc/shared": "6.3.4",
"acorn": "8.10.0",
"astring": "~1.8.6",
"estree-walker": "~2.0.2",
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/attribute-href-with-id-expression/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/attribute-href-with-id-expression/expected.js
index e21442b9c1..e1e041b8fe 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/attribute-href-with-id-expression/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/attribute-href-with-id-expression/expected.js
@@ -1,37 +1,37 @@
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment`
KIX`;
const stc0 = {
- key: 1,
+ key: 2,
};
function tmpl($api, $cmp, $slotset, $ctx) {
const {
fid: api_scoped_frag_id,
- t: api_text,
+ sp: api_static_part,
+ st: api_static_fragment,
h: api_element,
gid: api_scoped_id,
+ t: api_text,
} = $api;
return [
- api_element(
- "a",
- {
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
attrs: {
href: api_scoped_frag_id($cmp.narita),
},
- key: 0,
- },
- [api_text("KIX")]
- ),
+ }),
+ ]),
api_element("map", stc0, [
api_element("area", {
attrs: {
href: api_scoped_frag_id("#haneda"),
},
- key: 2,
+ key: 3,
}),
api_element("area", {
attrs: {
href: api_scoped_frag_id("#chubu"),
},
- key: 3,
+ key: 4,
}),
]),
api_element(
@@ -40,7 +40,7 @@ function tmpl($api, $cmp, $slotset, $ctx) {
attrs: {
id: api_scoped_id("#narita"),
},
- key: 4,
+ key: 5,
},
[api_text("Time to travel!")]
),
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/hidden-global-attr/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/hidden-global-attr/expected.js
index 520240d635..a4c778b9cf 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/hidden-global-attr/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/hidden-global-attr/expected.js
@@ -3,53 +3,51 @@ import { parseFragment, registerTemplate } from "lwc";
const $fragment1 = parseFragment`
boolean present
`;
const $fragment2 = parseFragment`
empty string, should be true
`;
const $fragment3 = parseFragment`
string value, should be true
`;
-const $fragment4 = parseFragment`
integer value, should be true
`;
+const $fragment4 = parseFragment`
computed value, should be resolved in component
`;
+const $fragment5 = parseFragment`
integer value, should be true
`;
const stc0 = {
props: {
hidden: true,
},
- key: 9,
+ key: 10,
};
const stc1 = {
props: {
hidden: true,
},
- key: 10,
+ key: 11,
};
const stc2 = {
props: {
hidden: true,
},
- key: 11,
+ key: 12,
};
const stc3 = {
props: {
hidden: true,
},
- key: 13,
+ key: 14,
};
function tmpl($api, $cmp, $slotset, $ctx) {
const {
st: api_static_fragment,
+ sp: api_static_part,
t: api_text,
- h: api_element,
c: api_custom_element,
} = $api;
return [
api_static_fragment($fragment1, 1),
api_static_fragment($fragment2, 3),
api_static_fragment($fragment3, 5),
- api_element(
- "p",
- {
+ api_static_fragment($fragment4, 7, [
+ api_static_part(0, {
attrs: {
hidden: $cmp.computed ? "" : null,
},
- key: 6,
- },
- [api_text("computed value, should be resolved in component")]
- ),
- api_static_fragment($fragment4, 8),
+ }),
+ ]),
+ api_static_fragment($fragment5, 9),
api_custom_element("x-foo", _xFoo, stc0, [api_text("boolean present")]),
api_custom_element("x-foo", _xFoo, stc1, [
api_text("empty string, should be true"),
@@ -64,7 +62,7 @@ function tmpl($api, $cmp, $slotset, $ctx) {
props: {
hidden: $cmp.computed,
},
- key: 12,
+ key: 13,
},
[api_text("computed value, should be resolved in component")]
),
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/required/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/required/expected.js
index 6f1ed49731..4e3f732f86 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/required/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attribute/required/expected.js
@@ -3,38 +3,36 @@ import { parseFragment, registerTemplate } from "lwc";
const $fragment1 = parseFragment`
`;
const $fragment2 = parseFragment`
`;
const $fragment3 = parseFragment`
`;
-const $fragment4 = parseFragment`
`;
+const $fragment4 = parseFragment`
`;
+const $fragment5 = parseFragment`
`;
const stc0 = {
- value: "computed value",
-};
-const stc1 = {
props: {
required: true,
},
- key: 9,
+ key: 10,
};
-const stc2 = {
+const stc1 = {
props: {
required: "",
},
- key: 10,
+ key: 11,
};
-const stc3 = {
+const stc2 = {
props: {
required: "other than true",
},
- key: 11,
+ key: 12,
};
-const stc4 = {
+const stc3 = {
props: {
required: "3",
},
- key: 13,
+ key: 14,
};
function tmpl($api, $cmp, $slotset, $ctx) {
const {
st: api_static_fragment,
- h: api_element,
+ sp: api_static_part,
t: api_text,
c: api_custom_element,
} = $api;
@@ -42,17 +40,17 @@ function tmpl($api, $cmp, $slotset, $ctx) {
api_static_fragment($fragment1, 1),
api_static_fragment($fragment2, 3),
api_static_fragment($fragment3, 5),
- api_element("input", {
- attrs: {
- required: $cmp.computed ? "" : null,
- },
- props: stc0,
- key: 6,
- }),
- api_static_fragment($fragment4, 8),
- api_custom_element("x-foo", _xFoo, stc1, [api_text("boolean present")]),
- api_custom_element("x-foo", _xFoo, stc2, [api_text("empty string")]),
- api_custom_element("x-foo", _xFoo, stc3, [api_text("string value")]),
+ api_static_fragment($fragment4, 7, [
+ api_static_part(0, {
+ attrs: {
+ required: $cmp.computed ? "" : null,
+ },
+ }),
+ ]),
+ api_static_fragment($fragment5, 9),
+ api_custom_element("x-foo", _xFoo, stc0, [api_text("boolean present")]),
+ api_custom_element("x-foo", _xFoo, stc1, [api_text("empty string")]),
+ api_custom_element("x-foo", _xFoo, stc2, [api_text("string value")]),
api_custom_element(
"x-foo",
_xFoo,
@@ -60,11 +58,11 @@ function tmpl($api, $cmp, $slotset, $ctx) {
props: {
required: $cmp.computed,
},
- key: 12,
+ key: 13,
},
[api_text("computed value, should be resolved in component")]
),
- api_custom_element("x-foo", _xFoo, stc4, [api_text("integer value")]),
+ api_custom_element("x-foo", _xFoo, stc3, [api_text("integer value")]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attributes-valid/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attributes-valid/expected.js
index a6d0380449..6bc16df8d1 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attributes-valid/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean-attributes-valid/expected.js
@@ -1,6 +1,7 @@
import _xFoo from "x/foo";
import { parseFragment, registerTemplate } from "lwc";
const $fragment1 = parseFragment`
x
`;
+const $fragment2 = parseFragment`
`;
const stc0 = {
props: {
autofocus: "true",
@@ -25,19 +26,18 @@ function tmpl($api, $cmp, $slotset, $ctx) {
const {
st: api_static_fragment,
c: api_custom_element,
- h: api_element,
+ sp: api_static_part,
} = $api;
return [
api_static_fragment($fragment1, 1),
api_custom_element("x-foo", _xFoo, stc0),
- api_element("input", {
- attrs: {
- readonly: $cmp.getReadOnly ? "" : null,
- disabled: "",
- title: "foo",
- },
- key: 3,
- }),
+ api_static_fragment($fragment2, 4, [
+ api_static_part(0, {
+ attrs: {
+ readonly: $cmp.getReadOnly ? "" : null,
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean/expected.js
index 34e923c106..2518ecfe43 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/boolean/expected.js
@@ -1,17 +1,17 @@
import { parseFragment, registerTemplate } from "lwc";
const $fragment1 = parseFragment`
x
`;
+const $fragment2 = parseFragment`
`;
function tmpl($api, $cmp, $slotset, $ctx) {
- const { st: api_static_fragment, h: api_element } = $api;
+ const { st: api_static_fragment, sp: api_static_part } = $api;
return [
api_static_fragment($fragment1, 1),
- api_element("input", {
- attrs: {
- readonly: $cmp.getReadOnly ? "" : null,
- disabled: "",
- title: "foo",
- },
- key: 2,
- }),
+ api_static_fragment($fragment2, 3, [
+ api_static_part(0, {
+ attrs: {
+ readonly: $cmp.getReadOnly ? "" : null,
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/actual.html
index 2398e2cb25..e7ad2c9711 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/actual.html
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/actual.html
@@ -3,9 +3,11 @@
+
+
description text
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/ast.json
index 8b61cc17d1..e7e9a5c324 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/ast.json
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/ast.json
@@ -4,10 +4,10 @@
"location": {
"startLine": 1,
"startColumn": 1,
- "endLine": 14,
+ "endLine": 16,
"endColumn": 12,
"start": 0,
- "end": 469,
+ "end": 566,
"startTag": {
"startLine": 1,
"startColumn": 1,
@@ -17,12 +17,12 @@
"end": 10
},
"endTag": {
- "startLine": 14,
+ "startLine": 16,
"startColumn": 1,
- "endLine": 14,
+ "endLine": 16,
"endColumn": 12,
- "start": 458,
- "end": 469
+ "start": 555,
+ "end": 566
}
},
"directives": [],
@@ -252,32 +252,111 @@
"listeners": [],
"children": []
},
+ {
+ "type": "Component",
+ "name": "x-textarea",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 6,
+ "startColumn": 5,
+ "endLine": 6,
+ "endColumn": 71,
+ "start": 209,
+ "end": 275,
+ "startTag": {
+ "startLine": 6,
+ "startColumn": 5,
+ "endLine": 6,
+ "endColumn": 58,
+ "start": 209,
+ "end": 262
+ },
+ "endTag": {
+ "startLine": 6,
+ "startColumn": 58,
+ "endLine": 6,
+ "endColumn": 71,
+ "start": 262,
+ "end": 275
+ }
+ },
+ "attributes": [],
+ "properties": [
+ {
+ "type": "Property",
+ "name": "id",
+ "attributeName": "id",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 9,
+ "name": "computed",
+ "location": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 30,
+ "start": 221,
+ "end": 234
+ }
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 30,
+ "start": 221,
+ "end": 234
+ }
+ },
+ {
+ "type": "Property",
+ "name": "ariaDescribedBy",
+ "attributeName": "aria-describedby",
+ "value": {
+ "type": "Literal",
+ "value": "bar baz"
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 31,
+ "endLine": 6,
+ "endColumn": 57,
+ "start": 235,
+ "end": 261
+ }
+ }
+ ],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
{
"type": "Element",
"name": "label",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
- "startLine": 7,
+ "startLine": 8,
"startColumn": 5,
- "endLine": 7,
+ "endLine": 8,
"endColumn": 41,
- "start": 210,
- "end": 246,
+ "start": 281,
+ "end": 317,
"startTag": {
- "startLine": 7,
+ "startLine": 8,
"startColumn": 5,
- "endLine": 7,
+ "endLine": 8,
"endColumn": 23,
- "start": 210,
- "end": 228
+ "start": 281,
+ "end": 299
},
"endTag": {
- "startLine": 7,
+ "startLine": 8,
"startColumn": 33,
- "endLine": 7,
+ "endLine": 8,
"endColumn": 41,
- "start": 238,
- "end": 246
+ "start": 309,
+ "end": 317
}
},
"attributes": [
@@ -289,12 +368,12 @@
"value": "boof"
},
"location": {
- "startLine": 7,
+ "startLine": 8,
"startColumn": 12,
- "endLine": 7,
+ "endLine": 8,
"endColumn": 22,
- "start": 217,
- "end": 227
+ "start": 288,
+ "end": 298
}
}
],
@@ -310,12 +389,12 @@
"value": "label text"
},
"location": {
- "startLine": 7,
+ "startLine": 8,
"startColumn": 23,
- "endLine": 7,
+ "endLine": 8,
"endColumn": 33,
- "start": 228,
- "end": 238
+ "start": 299,
+ "end": 309
}
}
]
@@ -325,19 +404,19 @@
"name": "input",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
- "startLine": 8,
+ "startLine": 9,
"startColumn": 5,
- "endLine": 8,
+ "endLine": 9,
"endColumn": 22,
- "start": 251,
- "end": 268,
+ "start": 322,
+ "end": 339,
"startTag": {
- "startLine": 8,
+ "startLine": 9,
"startColumn": 5,
- "endLine": 8,
+ "endLine": 9,
"endColumn": 22,
- "start": 251,
- "end": 268
+ "start": 322,
+ "end": 339
}
},
"attributes": [
@@ -349,12 +428,65 @@
"value": "boof"
},
"location": {
- "startLine": 8,
+ "startLine": 9,
"startColumn": 12,
- "endLine": 8,
+ "endLine": 9,
"endColumn": 21,
- "start": 258,
- "end": 267
+ "start": 329,
+ "end": 338
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "input",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 10,
+ "startColumn": 5,
+ "endLine": 10,
+ "endColumn": 26,
+ "start": 344,
+ "end": 365,
+ "startTag": {
+ "startLine": 10,
+ "startColumn": 5,
+ "endLine": 10,
+ "endColumn": 26,
+ "start": 344,
+ "end": 365
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "id",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 9,
+ "name": "computed",
+ "location": {
+ "startLine": 10,
+ "startColumn": 12,
+ "endLine": 10,
+ "endColumn": 25,
+ "start": 351,
+ "end": 364
+ }
+ },
+ "location": {
+ "startLine": 10,
+ "startColumn": 12,
+ "endLine": 10,
+ "endColumn": 25,
+ "start": 351,
+ "end": 364
}
}
],
@@ -371,41 +503,41 @@
"end": 7,
"name": "things",
"location": {
- "startLine": 10,
+ "startLine": 12,
"startColumn": 15,
- "endLine": 10,
+ "endLine": 12,
"endColumn": 32,
- "start": 284,
- "end": 301
+ "start": 381,
+ "end": 398
}
},
"item": {
"type": "Identifier",
"name": "thing",
"location": {
- "startLine": 10,
+ "startLine": 12,
"startColumn": 33,
- "endLine": 10,
+ "endLine": 12,
"endColumn": 49,
- "start": 302,
- "end": 318
+ "start": 399,
+ "end": 415
}
},
"location": {
- "startLine": 10,
+ "startLine": 12,
"startColumn": 5,
- "endLine": 13,
+ "endLine": 15,
"endColumn": 16,
- "start": 274,
- "end": 457
+ "start": 371,
+ "end": 554
},
"directiveLocation": {
- "startLine": 10,
+ "startLine": 12,
"startColumn": 15,
- "endLine": 10,
+ "endLine": 12,
"endColumn": 32,
- "start": 284,
- "end": 301
+ "start": 381,
+ "end": 398
},
"children": [
{
@@ -413,27 +545,27 @@
"name": "p",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 9,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 62,
- "start": 328,
- "end": 381,
+ "start": 425,
+ "end": 478,
"startTag": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 9,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 42,
- "start": 328,
- "end": 361
+ "start": 425,
+ "end": 458
},
"endTag": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 58,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 62,
- "start": 377,
- "end": 381
+ "start": 474,
+ "end": 478
}
},
"attributes": [
@@ -459,21 +591,21 @@
"computed": false,
"optional": false,
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 28,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 41,
- "start": 347,
- "end": 360
+ "start": 444,
+ "end": 457
}
},
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 28,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 41,
- "start": 347,
- "end": 360
+ "start": 444,
+ "end": 457
}
}
],
@@ -501,21 +633,21 @@
"computed": false,
"optional": false,
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 12,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 27,
- "start": 331,
- "end": 346
+ "start": 428,
+ "end": 443
}
},
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 12,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 27,
- "start": 331,
- "end": 346
+ "start": 428,
+ "end": 443
}
}
],
@@ -529,12 +661,12 @@
"value": "description text"
},
"location": {
- "startLine": 11,
+ "startLine": 13,
"startColumn": 42,
- "endLine": 11,
+ "endLine": 13,
"endColumn": 58,
- "start": 361,
- "end": 377
+ "start": 458,
+ "end": 474
}
}
]
@@ -544,19 +676,19 @@
"name": "input",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 9,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 60,
- "start": 390,
- "end": 441,
+ "start": 487,
+ "end": 538,
"startTag": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 9,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 60,
- "start": 390,
- "end": 441
+ "start": 487,
+ "end": 538
}
},
"attributes": [
@@ -582,21 +714,21 @@
"computed": false,
"optional": false,
"location": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 32,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 59,
- "start": 413,
- "end": 440
+ "start": 510,
+ "end": 537
}
},
"location": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 32,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 59,
- "start": 413,
- "end": 440
+ "start": 510,
+ "end": 537
}
}
],
@@ -624,21 +756,21 @@
"computed": false,
"optional": false,
"location": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 16,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 31,
- "start": 397,
- "end": 412
+ "start": 494,
+ "end": 509
}
},
"location": {
- "startLine": 12,
+ "startLine": 14,
"startColumn": 16,
- "endLine": 12,
+ "endLine": 14,
"endColumn": 31,
- "start": 397,
- "end": 412
+ "start": 494,
+ "end": 509
}
}
],
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/expected.js
index ddea1efb49..89a6b07f5c 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/id/expected.js
@@ -1,13 +1,16 @@
import _xSubject from "x/subject";
import _xDescription from "x/description";
import _xTextarea from "x/textarea";
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
function tmpl($api, $cmp, $slotset, $ctx) {
const {
gid: api_scoped_id,
c: api_custom_element,
t: api_text,
h: api_element,
+ sp: api_static_part,
+ st: api_static_fragment,
k: api_key,
i: api_iterator,
f: api_flatten,
@@ -38,13 +41,20 @@ function tmpl($api, $cmp, $slotset, $ctx) {
},
key: 3,
}),
+ api_custom_element("x-textarea", _xTextarea, {
+ props: {
+ id: api_scoped_id($cmp.computed),
+ ariaDescribedBy: api_scoped_id("bar baz"),
+ },
+ key: 4,
+ }),
api_element(
"label",
{
attrs: {
for: api_scoped_id("boof"),
},
- key: 4,
+ key: 5,
},
[api_text("label text")]
),
@@ -52,8 +62,15 @@ function tmpl($api, $cmp, $slotset, $ctx) {
attrs: {
id: api_scoped_id("boof"),
},
- key: 5,
+ key: 6,
}),
+ api_static_fragment($fragment1, 8, [
+ api_static_part(0, {
+ attrs: {
+ id: api_scoped_id($cmp.computed),
+ },
+ }),
+ ]),
api_iterator($cmp.things, function (thing) {
return [
api_element(
@@ -62,7 +79,7 @@ function tmpl($api, $cmp, $slotset, $ctx) {
attrs: {
id: api_scoped_id(thing.id),
},
- key: api_key(6, thing.key),
+ key: api_key(9, thing.key),
},
[api_text("description text")]
),
@@ -70,7 +87,7 @@ function tmpl($api, $cmp, $slotset, $ctx) {
attrs: {
"aria-describedby": api_scoped_id(thing.id),
},
- key: api_key(7, thing.key),
+ key: api_key(10, thing.key),
}),
];
}),
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/not-scoped/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/not-scoped/expected.js
index 9bb9c92e8a..18e98acad8 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/not-scoped/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/not-scoped/expected.js
@@ -1,17 +1,19 @@
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
function tmpl($api, $cmp, $slotset, $ctx) {
- const { h: api_element } = $api;
+ const { sp: api_static_part, st: api_static_fragment } = $api;
return [
- api_element("div", {
- attrs: {
- "aria-described-by": $cmp.scoped,
- "aria-active-descendant": $cmp.scoped,
- "aria-error-message": $cmp.scoped,
- "aria-flow-to": $cmp.scoped,
- "aria-labelled-by": $cmp.scoped,
- },
- key: 0,
- }),
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
+ attrs: {
+ "aria-described-by": $cmp.scoped,
+ "aria-active-descendant": $cmp.scoped,
+ "aria-error-message": $cmp.scoped,
+ "aria-flow-to": $cmp.scoped,
+ "aria-labelled-by": $cmp.scoped,
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/scoped/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/scoped/expected.js
index 9ae73e1463..5b8214dccd 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/scoped/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/scoped-id/expression/scoped/expected.js
@@ -1,21 +1,27 @@
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
function tmpl($api, $cmp, $slotset, $ctx) {
- const { gid: api_scoped_id, h: api_element } = $api;
+ const {
+ gid: api_scoped_id,
+ sp: api_static_part,
+ st: api_static_fragment,
+ } = $api;
return [
- api_element("div", {
- attrs: {
- "aria-describedby": api_scoped_id($cmp.foo),
- "aria-activedescendant": api_scoped_id($cmp.foo),
- "aria-errormessage": api_scoped_id($cmp.foo),
- "aria-flowto": api_scoped_id($cmp.foo),
- "aria-labelledby": api_scoped_id($cmp.foo),
- "aria-controls": api_scoped_id($cmp.foo),
- "aria-details": api_scoped_id($cmp.foo),
- "aria-owns": api_scoped_id($cmp.foo),
- for: api_scoped_id($cmp.foo),
- },
- key: 0,
- }),
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
+ attrs: {
+ "aria-describedby": api_scoped_id($cmp.foo),
+ "aria-activedescendant": api_scoped_id($cmp.foo),
+ "aria-errormessage": api_scoped_id($cmp.foo),
+ "aria-flowto": api_scoped_id($cmp.foo),
+ "aria-labelledby": api_scoped_id($cmp.foo),
+ "aria-controls": api_scoped_id($cmp.foo),
+ "aria-details": api_scoped_id($cmp.foo),
+ "aria-owns": api_scoped_id($cmp.foo),
+ for: api_scoped_id($cmp.foo),
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/actual.html
new file mode 100644
index 0000000000..1f5f4397b3
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/actual.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/ast.json
new file mode 100644
index 0000000000..843b8484a4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/ast.json
@@ -0,0 +1,155 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 4,
+ "endColumn": 12,
+ "start": 0,
+ "end": 106,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 11,
+ "start": 0,
+ "end": 10
+ },
+ "endTag": {
+ "startLine": 4,
+ "startColumn": 1,
+ "endLine": 4,
+ "endColumn": 12,
+ "start": 95,
+ "end": 106
+ }
+ },
+ "directives": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 2,
+ "endColumn": 40,
+ "start": 15,
+ "end": 50,
+ "startTag": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 2,
+ "endColumn": 34,
+ "start": 15,
+ "end": 44
+ },
+ "endTag": {
+ "startLine": 2,
+ "startColumn": 34,
+ "endLine": 2,
+ "endColumn": 40,
+ "start": 44,
+ "end": 50
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "spellcheck",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 11,
+ "name": "spellCheck",
+ "location": {
+ "startLine": 2,
+ "startColumn": 10,
+ "endLine": 2,
+ "endColumn": 33,
+ "start": 20,
+ "end": 43
+ }
+ },
+ "location": {
+ "startLine": 2,
+ "startColumn": 10,
+ "endLine": 2,
+ "endColumn": 33,
+ "start": 20,
+ "end": 43
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Component",
+ "name": "x-foo",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 3,
+ "startColumn": 5,
+ "endLine": 3,
+ "endColumn": 44,
+ "start": 55,
+ "end": 94,
+ "startTag": {
+ "startLine": 3,
+ "startColumn": 5,
+ "endLine": 3,
+ "endColumn": 36,
+ "start": 55,
+ "end": 86
+ },
+ "endTag": {
+ "startLine": 3,
+ "startColumn": 36,
+ "endLine": 3,
+ "endColumn": 44,
+ "start": 86,
+ "end": 94
+ }
+ },
+ "attributes": [],
+ "properties": [
+ {
+ "type": "Property",
+ "name": "spellcheck",
+ "attributeName": "spellcheck",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 11,
+ "name": "spellCheck",
+ "location": {
+ "startLine": 3,
+ "startColumn": 12,
+ "endLine": 3,
+ "endColumn": 35,
+ "start": 62,
+ "end": 85
+ }
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 12,
+ "endLine": 3,
+ "endColumn": 35,
+ "start": 62,
+ "end": 85
+ }
+ }
+ ],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/expected.js
new file mode 100644
index 0000000000..a9ae1f7399
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/expected.js
@@ -0,0 +1,28 @@
+import _xFoo from "x/foo";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const {
+ sp: api_static_part,
+ st: api_static_fragment,
+ c: api_custom_element,
+ } = $api;
+ return [
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
+ attrs: {
+ spellcheck: $cmp.spellCheck,
+ },
+ }),
+ ]),
+ api_custom_element("x-foo", _xFoo, {
+ props: {
+ spellcheck: $cmp.spellCheck,
+ },
+ key: 2,
+ }),
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.stylesheets = [];
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/spellcheck/expression/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/tabindex-computed/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/tabindex-computed/expected.js
index 3710b5dc9f..f608bbc9f5 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/tabindex-computed/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/tabindex-computed/expected.js
@@ -1,28 +1,26 @@
import _xFoo from "x/foo";
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment`valid
`;
function tmpl($api, $cmp, $slotset, $ctx) {
const {
ti: api_tab_index,
- t: api_text,
- h: api_element,
+ sp: api_static_part,
+ st: api_static_fragment,
c: api_custom_element,
} = $api;
return [
- api_element(
- "p",
- {
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
attrs: {
tabindex: api_tab_index($cmp.computed),
},
- key: 0,
- },
- [api_text("valid")]
- ),
+ }),
+ ]),
api_custom_element("x-foo", _xFoo, {
props: {
tabIndex: api_tab_index($cmp.computed),
},
- key: 1,
+ key: 2,
}),
];
/*LWC compiler vX.X.X*/
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/unquoted-value-unary/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/unquoted-value-unary/expected.js
index 9d558c4d43..14942c30ff 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/unquoted-value-unary/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/attributes/unquoted-value-unary/expected.js
@@ -1,13 +1,15 @@
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
function tmpl($api, $cmp, $slotset, $ctx) {
- const { h: api_element } = $api;
+ const { sp: api_static_part, st: api_static_fragment } = $api;
return [
- api_element("input", {
- attrs: {
- title: $cmp.myValue,
- },
- key: 0,
- }),
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
+ attrs: {
+ title: $cmp.myValue,
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/actual.html
new file mode 100644
index 0000000000..17248f5aca
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/actual.html
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/ast.json
new file mode 100644
index 0000000000..196882a640
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/ast.json
@@ -0,0 +1,301 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 10,
+ "endColumn": 12,
+ "start": 0,
+ "end": 264,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 11,
+ "start": 0,
+ "end": 10
+ },
+ "endTag": {
+ "startLine": 10,
+ "startColumn": 1,
+ "endLine": 10,
+ "endColumn": 12,
+ "start": 253,
+ "end": 264
+ }
+ },
+ "directives": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 9,
+ "endColumn": 11,
+ "start": 15,
+ "end": 252,
+ "startTag": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 2,
+ "endColumn": 10,
+ "start": 15,
+ "end": 20
+ },
+ "endTag": {
+ "startLine": 9,
+ "startColumn": 5,
+ "endLine": 9,
+ "endColumn": 11,
+ "start": 246,
+ "end": 252
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": [
+ {
+ "type": "ForEach",
+ "expression": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 6,
+ "name": "items",
+ "location": {
+ "startLine": 3,
+ "startColumn": 19,
+ "endLine": 3,
+ "endColumn": 35,
+ "start": 39,
+ "end": 55
+ }
+ },
+ "item": {
+ "type": "Identifier",
+ "name": "item",
+ "location": {
+ "startLine": 3,
+ "startColumn": 36,
+ "endLine": 3,
+ "endColumn": 51,
+ "start": 56,
+ "end": 71
+ }
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 8,
+ "endColumn": 20,
+ "start": 29,
+ "end": 241
+ },
+ "directiveLocation": {
+ "startLine": 3,
+ "startColumn": 19,
+ "endLine": 3,
+ "endColumn": 35,
+ "start": 39,
+ "end": 55
+ },
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 4,
+ "startColumn": 13,
+ "endLine": 7,
+ "endColumn": 19,
+ "start": 85,
+ "end": 221,
+ "startTag": {
+ "startLine": 4,
+ "startColumn": 13,
+ "endLine": 4,
+ "endColumn": 33,
+ "start": 85,
+ "end": 105
+ },
+ "endTag": {
+ "startLine": 7,
+ "startColumn": 13,
+ "endLine": 7,
+ "endColumn": 19,
+ "start": 215,
+ "end": 221
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "Key",
+ "value": {
+ "type": "MemberExpression",
+ "start": 1,
+ "end": 9,
+ "object": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 5,
+ "name": "item"
+ },
+ "property": {
+ "type": "Identifier",
+ "start": 6,
+ "end": 9,
+ "name": "key"
+ },
+ "computed": false,
+ "optional": false,
+ "location": {
+ "startLine": 4,
+ "startColumn": 18,
+ "endLine": 4,
+ "endColumn": 32,
+ "start": 90,
+ "end": 104
+ }
+ },
+ "location": {
+ "startLine": 4,
+ "startColumn": 18,
+ "endLine": 4,
+ "endColumn": 32,
+ "start": 90,
+ "end": 104
+ }
+ }
+ ],
+ "listeners": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 5,
+ "startColumn": 17,
+ "endLine": 5,
+ "endColumn": 49,
+ "start": 122,
+ "end": 154,
+ "startTag": {
+ "startLine": 5,
+ "startColumn": 17,
+ "endLine": 5,
+ "endColumn": 42,
+ "start": 122,
+ "end": 147
+ },
+ "endTag": {
+ "startLine": 5,
+ "startColumn": 42,
+ "endLine": 5,
+ "endColumn": 49,
+ "start": 147,
+ "end": 154
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-dynamic",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 4,
+ "name": "foo",
+ "location": {
+ "startLine": 5,
+ "startColumn": 23,
+ "endLine": 5,
+ "endColumn": 41,
+ "start": 128,
+ "end": 146
+ }
+ },
+ "location": {
+ "startLine": 5,
+ "startColumn": 23,
+ "endLine": 5,
+ "endColumn": 41,
+ "start": 128,
+ "end": 146
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 48,
+ "start": 171,
+ "end": 202,
+ "startTag": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 41,
+ "start": 171,
+ "end": 195
+ },
+ "endTag": {
+ "startLine": 6,
+ "startColumn": 41,
+ "endLine": 6,
+ "endColumn": 48,
+ "start": 195,
+ "end": 202
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-static",
+ "value": {
+ "type": "Literal",
+ "value": "bar"
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 23,
+ "endLine": 6,
+ "endColumn": 40,
+ "start": 177,
+ "end": 194
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/expected.js
new file mode 100644
index 0000000000..3dc577646d
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/expected.js
@@ -0,0 +1,42 @@
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
+const $fragment2 = parseFragment``;
+const stc0 = {
+ key: 0,
+};
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const {
+ k: api_key,
+ sp: api_static_part,
+ st: api_static_fragment,
+ h: api_element,
+ i: api_iterator,
+ } = $api;
+ return [
+ api_element(
+ "div",
+ stc0,
+ api_iterator($cmp.items, function (item) {
+ return api_element(
+ "div",
+ {
+ key: api_key(1, item.key),
+ },
+ [
+ api_static_fragment($fragment1, 3, [
+ api_static_part(0, {
+ attrs: {
+ "data-dynamic": $cmp.foo,
+ },
+ }),
+ ]),
+ api_static_fragment($fragment2, 5),
+ ]
+ );
+ })
+ ),
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.stylesheets = [];
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-for-each/static-content-optimization/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/actual.html
new file mode 100644
index 0000000000..4440802a11
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/actual.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/ast.json
new file mode 100644
index 0000000000..388773f44c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/ast.json
@@ -0,0 +1,459 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 14,
+ "endColumn": 12,
+ "start": 0,
+ "end": 467,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 11,
+ "start": 0,
+ "end": 10
+ },
+ "endTag": {
+ "startLine": 14,
+ "startColumn": 1,
+ "endLine": 14,
+ "endColumn": 12,
+ "start": 456,
+ "end": 467
+ }
+ },
+ "directives": [],
+ "children": [
+ {
+ "type": "IfBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 7,
+ "name": "showIf",
+ "location": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 30,
+ "start": 25,
+ "end": 40
+ }
+ },
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 5,
+ "endColumn": 16,
+ "start": 15,
+ "end": 154
+ },
+ "directiveLocation": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 30,
+ "start": 25,
+ "end": 40
+ },
+ "children": [
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 46,
+ "start": 50,
+ "end": 87,
+ "startTag": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 39,
+ "start": 50,
+ "end": 80
+ },
+ "endTag": {
+ "startLine": 3,
+ "startColumn": 39,
+ "endLine": 3,
+ "endColumn": 46,
+ "start": 80,
+ "end": 87
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-dynamic",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 9,
+ "name": "insideIf",
+ "location": {
+ "startLine": 3,
+ "startColumn": 15,
+ "endLine": 3,
+ "endColumn": 38,
+ "start": 56,
+ "end": 79
+ }
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 15,
+ "endLine": 3,
+ "endColumn": 38,
+ "start": 56,
+ "end": 79
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 4,
+ "startColumn": 9,
+ "endLine": 4,
+ "endColumn": 51,
+ "start": 96,
+ "end": 138,
+ "startTag": {
+ "startLine": 4,
+ "startColumn": 9,
+ "endLine": 4,
+ "endColumn": 44,
+ "start": 96,
+ "end": 131
+ },
+ "endTag": {
+ "startLine": 4,
+ "startColumn": 44,
+ "endLine": 4,
+ "endColumn": 51,
+ "start": 131,
+ "end": 138
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-static",
+ "value": {
+ "type": "Literal",
+ "value": "staticInsideIf"
+ },
+ "location": {
+ "startLine": 4,
+ "startColumn": 15,
+ "endLine": 4,
+ "endColumn": 43,
+ "start": 102,
+ "end": 130
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ],
+ "else": {
+ "type": "ElseifBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 11,
+ "name": "showElseIf",
+ "location": {
+ "startLine": 6,
+ "startColumn": 15,
+ "endLine": 6,
+ "endColumn": 38,
+ "start": 169,
+ "end": 192
+ }
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 5,
+ "endLine": 9,
+ "endColumn": 16,
+ "start": 159,
+ "end": 314
+ },
+ "directiveLocation": {
+ "startLine": 6,
+ "startColumn": 15,
+ "endLine": 6,
+ "endColumn": 38,
+ "start": 169,
+ "end": 192
+ },
+ "children": [
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 7,
+ "startColumn": 9,
+ "endLine": 7,
+ "endColumn": 50,
+ "start": 202,
+ "end": 243,
+ "startTag": {
+ "startLine": 7,
+ "startColumn": 9,
+ "endLine": 7,
+ "endColumn": 43,
+ "start": 202,
+ "end": 236
+ },
+ "endTag": {
+ "startLine": 7,
+ "startColumn": 43,
+ "endLine": 7,
+ "endColumn": 50,
+ "start": 236,
+ "end": 243
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-dynamic",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 13,
+ "name": "insideElseIf",
+ "location": {
+ "startLine": 7,
+ "startColumn": 15,
+ "endLine": 7,
+ "endColumn": 42,
+ "start": 208,
+ "end": 235
+ }
+ },
+ "location": {
+ "startLine": 7,
+ "startColumn": 15,
+ "endLine": 7,
+ "endColumn": 42,
+ "start": 208,
+ "end": 235
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 8,
+ "startColumn": 9,
+ "endLine": 8,
+ "endColumn": 55,
+ "start": 252,
+ "end": 298,
+ "startTag": {
+ "startLine": 8,
+ "startColumn": 9,
+ "endLine": 8,
+ "endColumn": 48,
+ "start": 252,
+ "end": 291
+ },
+ "endTag": {
+ "startLine": 8,
+ "startColumn": 48,
+ "endLine": 8,
+ "endColumn": 55,
+ "start": 291,
+ "end": 298
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-static",
+ "value": {
+ "type": "Literal",
+ "value": "staticInsideElseIf"
+ },
+ "location": {
+ "startLine": 8,
+ "startColumn": 15,
+ "endLine": 8,
+ "endColumn": 47,
+ "start": 258,
+ "end": 290
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ],
+ "else": {
+ "type": "ElseBlock",
+ "location": {
+ "startLine": 10,
+ "startColumn": 5,
+ "endLine": 13,
+ "endColumn": 16,
+ "start": 319,
+ "end": 455
+ },
+ "directiveLocation": {
+ "startLine": 10,
+ "startColumn": 15,
+ "endLine": 10,
+ "endColumn": 23,
+ "start": 329,
+ "end": 337
+ },
+ "children": [
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 11,
+ "startColumn": 9,
+ "endLine": 11,
+ "endColumn": 48,
+ "start": 347,
+ "end": 386,
+ "startTag": {
+ "startLine": 11,
+ "startColumn": 9,
+ "endLine": 11,
+ "endColumn": 41,
+ "start": 347,
+ "end": 379
+ },
+ "endTag": {
+ "startLine": 11,
+ "startColumn": 41,
+ "endLine": 11,
+ "endColumn": 48,
+ "start": 379,
+ "end": 386
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-dynamic",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 11,
+ "name": "insideElse",
+ "location": {
+ "startLine": 11,
+ "startColumn": 15,
+ "endLine": 11,
+ "endColumn": 40,
+ "start": 353,
+ "end": 378
+ }
+ },
+ "location": {
+ "startLine": 11,
+ "startColumn": 15,
+ "endLine": 11,
+ "endColumn": 40,
+ "start": 353,
+ "end": 378
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "span",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 12,
+ "startColumn": 9,
+ "endLine": 12,
+ "endColumn": 53,
+ "start": 395,
+ "end": 439,
+ "startTag": {
+ "startLine": 12,
+ "startColumn": 9,
+ "endLine": 12,
+ "endColumn": 46,
+ "start": 395,
+ "end": 432
+ },
+ "endTag": {
+ "startLine": 12,
+ "startColumn": 46,
+ "endLine": 12,
+ "endColumn": 53,
+ "start": 432,
+ "end": 439
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-static",
+ "value": {
+ "type": "Literal",
+ "value": "staticInsideElse"
+ },
+ "location": {
+ "startLine": 12,
+ "startColumn": 15,
+ "endLine": 12,
+ "endColumn": 45,
+ "start": 401,
+ "end": 431
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/expected.js
new file mode 100644
index 0000000000..d420376361
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/expected.js
@@ -0,0 +1,63 @@
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
+const $fragment2 = parseFragment``;
+const $fragment3 = parseFragment``;
+const $fragment4 = parseFragment``;
+const $fragment5 = parseFragment``;
+const $fragment6 = parseFragment``;
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const {
+ sp: api_static_part,
+ st: api_static_fragment,
+ fr: api_fragment,
+ } = $api;
+ return [
+ $cmp.showIf
+ ? api_fragment(
+ 0,
+ [
+ api_static_fragment($fragment1, 2, [
+ api_static_part(0, {
+ attrs: {
+ "data-dynamic": $cmp.insideIf,
+ },
+ }),
+ ]),
+ api_static_fragment($fragment2, 4),
+ ],
+ 0
+ )
+ : $cmp.showElseIf
+ ? api_fragment(
+ 0,
+ [
+ api_static_fragment($fragment3, 6, [
+ api_static_part(0, {
+ attrs: {
+ "data-dynamic": $cmp.insideElseIf,
+ },
+ }),
+ ]),
+ api_static_fragment($fragment4, 8),
+ ],
+ 0
+ )
+ : api_fragment(
+ 0,
+ [
+ api_static_fragment($fragment5, 10, [
+ api_static_part(0, {
+ attrs: {
+ "data-dynamic": $cmp.insideElse,
+ },
+ }),
+ ]),
+ api_static_fragment($fragment6, 12),
+ ],
+ 0
+ ),
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.stylesheets = [];
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-lwc-if-else/static-content-optimization/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-ref/dynamic-ref/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-ref/dynamic-ref/expected.js
index 6c363c3381..dea4129b51 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-ref/dynamic-ref/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/directive-ref/dynamic-ref/expected.js
@@ -1,14 +1,16 @@
-import { registerTemplate } from "lwc";
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
function tmpl($api, $cmp, $slotset, $ctx) {
- const { h: api_element } = $api;
+ const { sp: api_static_part, st: api_static_fragment } = $api;
return [
- api_element("div", {
- attrs: {
- dynamic: $cmp.dynamic,
- },
- ref: "foo",
- key: 0,
- }),
+ api_static_fragment($fragment1, 1, [
+ api_static_part(0, {
+ ref: "foo",
+ attrs: {
+ dynamic: $cmp.dynamic,
+ },
+ }),
+ ]),
];
/*LWC compiler vX.X.X*/
}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/renderer-hooks/svg/href-with-expression-value/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/renderer-hooks/svg/href-with-expression-value/expected.js
index 0485566f1a..646a7c8b47 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/renderer-hooks/svg/href-with-expression-value/expected.js
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/renderer-hooks/svg/href-with-expression-value/expected.js
@@ -1,4 +1,5 @@
-import { registerTemplate, renderer } from "lwc";
+import { parseSVGFragment, registerTemplate, renderer } from "lwc";
+const $fragment1 = parseSVGFragment``;
const stc0 = {
attrs: {
viewBox: "0 0 30 10",
@@ -8,27 +9,29 @@ const stc0 = {
svg: true,
};
function tmpl($api, $cmp, $slotset, $ctx) {
- const { gid: api_scoped_id, h: api_element, fid: api_scoped_frag_id } = $api;
+ const {
+ gid: api_scoped_id,
+ sp: api_static_part,
+ st: api_static_fragment,
+ fid: api_scoped_frag_id,
+ h: api_element,
+ } = $api;
return [
api_element("svg", stc0, [
- api_element("circle", {
- attrs: {
- id: api_scoped_id($cmp.id),
- cx: "5",
- cy: "5",
- r: "4",
- stroke: "black",
- },
- key: 1,
- svg: true,
- }),
+ api_static_fragment($fragment1, 2, [
+ api_static_part(0, {
+ attrs: {
+ id: api_scoped_id($cmp.id),
+ },
+ }),
+ ]),
api_element("use", {
attrs: {
href: api_scoped_frag_id($cmp.id),
x: "10",
fill: "blue",
},
- key: 2,
+ key: 3,
svg: true,
renderer: renderer,
}),
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/actual.html
new file mode 100644
index 0000000000..7c3348e23e
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/actual.html
@@ -0,0 +1,13 @@
+
+
+
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/ast.json
new file mode 100644
index 0000000000..a7dd21552b
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/ast.json
@@ -0,0 +1,415 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 13,
+ "endColumn": 12,
+ "start": 0,
+ "end": 290,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 11,
+ "start": 0,
+ "end": 10
+ },
+ "endTag": {
+ "startLine": 13,
+ "startColumn": 1,
+ "endLine": 13,
+ "endColumn": 12,
+ "start": 279,
+ "end": 290
+ }
+ },
+ "directives": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 12,
+ "endColumn": 11,
+ "start": 15,
+ "end": 278,
+ "startTag": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 2,
+ "endColumn": 10,
+ "start": 15,
+ "end": 20
+ },
+ "endTag": {
+ "startLine": 12,
+ "startColumn": 5,
+ "endLine": 12,
+ "endColumn": 11,
+ "start": 272,
+ "end": 278
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 20,
+ "start": 29,
+ "end": 40,
+ "startTag": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 14,
+ "start": 29,
+ "end": 34
+ },
+ "endTag": {
+ "startLine": 3,
+ "startColumn": 14,
+ "endLine": 3,
+ "endColumn": 20,
+ "start": 34,
+ "end": 40
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 4,
+ "startColumn": 9,
+ "endLine": 9,
+ "endColumn": 15,
+ "start": 49,
+ "end": 194,
+ "startTag": {
+ "startLine": 4,
+ "startColumn": 9,
+ "endLine": 4,
+ "endColumn": 14,
+ "start": 49,
+ "end": 54
+ },
+ "endTag": {
+ "startLine": 9,
+ "startColumn": 9,
+ "endLine": 9,
+ "endColumn": 15,
+ "start": 188,
+ "end": 194
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 5,
+ "startColumn": 13,
+ "endLine": 8,
+ "endColumn": 19,
+ "start": 67,
+ "end": 179,
+ "startTag": {
+ "startLine": 5,
+ "startColumn": 13,
+ "endLine": 5,
+ "endColumn": 18,
+ "start": 67,
+ "end": 72
+ },
+ "endTag": {
+ "startLine": 8,
+ "startColumn": 13,
+ "endLine": 8,
+ "endColumn": 19,
+ "start": 173,
+ "end": 179
+ }
+ },
+ "attributes": [],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": [
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 44,
+ "start": 89,
+ "end": 116,
+ "startTag": {
+ "startLine": 6,
+ "startColumn": 17,
+ "endLine": 6,
+ "endColumn": 38,
+ "start": 89,
+ "end": 110
+ },
+ "endTag": {
+ "startLine": 6,
+ "startColumn": 38,
+ "endLine": 6,
+ "endColumn": 44,
+ "start": 110,
+ "end": 116
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-name",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 4,
+ "name": "foo",
+ "location": {
+ "startLine": 6,
+ "startColumn": 22,
+ "endLine": 6,
+ "endColumn": 37,
+ "start": 94,
+ "end": 109
+ }
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 22,
+ "endLine": 6,
+ "endColumn": 37,
+ "start": 94,
+ "end": 109
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 7,
+ "startColumn": 17,
+ "endLine": 7,
+ "endColumn": 44,
+ "start": 133,
+ "end": 160,
+ "startTag": {
+ "startLine": 7,
+ "startColumn": 17,
+ "endLine": 7,
+ "endColumn": 38,
+ "start": 133,
+ "end": 154
+ },
+ "endTag": {
+ "startLine": 7,
+ "startColumn": 38,
+ "endLine": 7,
+ "endColumn": 44,
+ "start": 154,
+ "end": 160
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-name",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 4,
+ "name": "baz",
+ "location": {
+ "startLine": 7,
+ "startColumn": 22,
+ "endLine": 7,
+ "endColumn": 37,
+ "start": 138,
+ "end": 153
+ }
+ },
+ "location": {
+ "startLine": 7,
+ "startColumn": 22,
+ "endLine": 7,
+ "endColumn": 37,
+ "start": 138,
+ "end": 153
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 10,
+ "startColumn": 9,
+ "endLine": 10,
+ "endColumn": 36,
+ "start": 203,
+ "end": 230,
+ "startTag": {
+ "startLine": 10,
+ "startColumn": 9,
+ "endLine": 10,
+ "endColumn": 30,
+ "start": 203,
+ "end": 224
+ },
+ "endTag": {
+ "startLine": 10,
+ "startColumn": 30,
+ "endLine": 10,
+ "endColumn": 36,
+ "start": 224,
+ "end": 230
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-name",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 4,
+ "name": "bar",
+ "location": {
+ "startLine": 10,
+ "startColumn": 14,
+ "endLine": 10,
+ "endColumn": 29,
+ "start": 208,
+ "end": 223
+ }
+ },
+ "location": {
+ "startLine": 10,
+ "startColumn": 14,
+ "endLine": 10,
+ "endColumn": 29,
+ "start": 208,
+ "end": 223
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ },
+ {
+ "type": "Element",
+ "name": "div",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "location": {
+ "startLine": 11,
+ "startColumn": 9,
+ "endLine": 11,
+ "endColumn": 37,
+ "start": 239,
+ "end": 267,
+ "startTag": {
+ "startLine": 11,
+ "startColumn": 9,
+ "endLine": 11,
+ "endColumn": 31,
+ "start": 239,
+ "end": 261
+ },
+ "endTag": {
+ "startLine": 11,
+ "startColumn": 31,
+ "endLine": 11,
+ "endColumn": 37,
+ "start": 261,
+ "end": 267
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "data-name",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 5,
+ "name": "quux",
+ "location": {
+ "startLine": 11,
+ "startColumn": 14,
+ "endLine": 11,
+ "endColumn": 30,
+ "start": 244,
+ "end": 260
+ }
+ },
+ "location": {
+ "startLine": 11,
+ "startColumn": 14,
+ "endLine": 11,
+ "endColumn": 30,
+ "start": 244,
+ "end": 260
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/expected.js
new file mode 100644
index 0000000000..267441ba92
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/expected.js
@@ -0,0 +1,32 @@
+import { parseFragment, registerTemplate } from "lwc";
+const $fragment1 = parseFragment``;
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const { sp: api_static_part, st: api_static_fragment } = $api;
+ return [
+ api_static_fragment($fragment1, 1, [
+ api_static_part(4, {
+ attrs: {
+ "data-name": $cmp.foo,
+ },
+ }),
+ api_static_part(5, {
+ attrs: {
+ "data-name": $cmp.baz,
+ },
+ }),
+ api_static_part(6, {
+ attrs: {
+ "data-name": $cmp.bar,
+ },
+ }),
+ api_static_part(7, {
+ attrs: {
+ "data-name": $cmp.quux,
+ },
+ }),
+ ]),
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.stylesheets = [];
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data-attrs-only/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data/actual.html
index 631e652aed..1a1b8f2f02 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data/actual.html
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/static-content/deep-data/actual.html
@@ -5,9 +5,11 @@