diff --git a/packages/@lwc/errors/src/compiler/error-info/template-transform.ts b/packages/@lwc/errors/src/compiler/error-info/template-transform.ts
index 50cd4849d9..820ba0caf0 100644
--- a/packages/@lwc/errors/src/compiler/error-info/template-transform.ts
+++ b/packages/@lwc/errors/src/compiler/error-info/template-transform.ts
@@ -393,6 +393,7 @@ export const ParserDiagnostics = {
url: '',
},
+ // TODO [#3100]: Update message to point to external documentation once available.
SLOT_TAG_CANNOT_HAVE_DIRECTIVES: {
code: 1082,
message:
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures.spec.ts b/packages/@lwc/template-compiler/src/__tests__/fixtures.spec.ts
index f086154725..53b7a0c07d 100644
--- a/packages/@lwc/template-compiler/src/__tests__/fixtures.spec.ts
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures.spec.ts
@@ -15,7 +15,7 @@ import compiler, { Config } from '../index';
describe('fixtures', () => {
testFixtureDir(
{
- root: path.resolve(__dirname, 'fixtures'),
+ root: path.resolve(__dirname, 'fixtures', 'scoped-slots'),
pattern: '**/actual.html',
},
({ src, dirname }) => {
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/actual.html
new file mode 100644
index 0000000000..2866bfca00
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/actual.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/ast.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/ast.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/expected.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/metadata.json
new file mode 100644
index 0000000000..739a11a207
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-after/metadata.json
@@ -0,0 +1,15 @@
+{
+ "warnings": [
+ {
+ "code": 1172,
+ "message": "LWC1172: Invalid duplicate scoped slots (default)",
+ "level": 1,
+ "location": {
+ "line": 11,
+ "column": 5,
+ "start": 320,
+ "length": 46
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/actual.html
new file mode 100644
index 0000000000..1dc62bc404
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/actual.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/ast.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/ast.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/expected.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/metadata.json
new file mode 100644
index 0000000000..3c743fc6e4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-default-slot-before/metadata.json
@@ -0,0 +1,26 @@
+{
+ "warnings": [
+ {
+ "code": 1173,
+ "message": "LWC1173: Mixing slot types disallowed for same (default) slot.",
+ "level": 1,
+ "location": {
+ "line": 4,
+ "column": 9,
+ "start": 131,
+ "length": 13
+ }
+ },
+ {
+ "code": 1172,
+ "message": "LWC1172: Invalid duplicate scoped slots (default)",
+ "level": 1,
+ "location": {
+ "line": 7,
+ "column": 9,
+ "start": 209,
+ "length": 46
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/actual.html
new file mode 100644
index 0000000000..e21da8728b
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/actual.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/ast.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/ast.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/expected.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/metadata.json
new file mode 100644
index 0000000000..1732d6dcda
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/invalid/duplicate-named-slot-after/metadata.json
@@ -0,0 +1,15 @@
+{
+ "warnings": [
+ {
+ "code": 1172,
+ "message": "LWC1172: Invalid duplicate scoped slots (name=\"slotname1\")",
+ "level": 1,
+ "location": {
+ "line": 8,
+ "column": 5,
+ "start": 243,
+ "length": 63
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/actual.html
new file mode 100644
index 0000000000..b3f875496c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/actual.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/ast.json
new file mode 100644
index 0000000000..6688af5f91
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/ast.json
@@ -0,0 +1,250 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 8,
+ "endColumn": 12,
+ "start": 0,
+ "end": 266,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 35,
+ "start": 0,
+ "end": 34
+ },
+ "endTag": {
+ "startLine": 8,
+ "startColumn": 1,
+ "endLine": 8,
+ "endColumn": 12,
+ "start": 255,
+ "end": 266
+ }
+ },
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "RenderMode",
+ "value": {
+ "type": "Literal",
+ "value": "light"
+ },
+ "location": {
+ "startLine": 1,
+ "startColumn": 11,
+ "endLine": 1,
+ "endColumn": 34,
+ "start": 10,
+ "end": 33
+ }
+ }
+ ],
+ "children": [
+ {
+ "type": "IfBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 13,
+ "name": "showStandard",
+ "location": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 36,
+ "start": 49,
+ "end": 70
+ }
+ },
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 4,
+ "endColumn": 16,
+ "start": 39,
+ "end": 126
+ },
+ "directiveLocation": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 36,
+ "start": 49,
+ "end": 70
+ },
+ "children": [
+ {
+ "type": "Slot",
+ "name": "slot",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "slotName": "slotname1",
+ "location": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 39,
+ "start": 80,
+ "end": 110,
+ "startTag": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 32,
+ "start": 80,
+ "end": 103
+ },
+ "endTag": {
+ "startLine": 3,
+ "startColumn": 32,
+ "endLine": 3,
+ "endColumn": 39,
+ "start": 103,
+ "end": 110
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "name",
+ "value": {
+ "type": "Literal",
+ "value": "slotname1"
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 15,
+ "endLine": 3,
+ "endColumn": 31,
+ "start": 86,
+ "end": 102
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [],
+ "listeners": [],
+ "children": []
+ }
+ ],
+ "else": {
+ "type": "ElseifBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 12,
+ "name": "showVariant",
+ "location": {
+ "startLine": 5,
+ "startColumn": 15,
+ "endLine": 5,
+ "endColumn": 39,
+ "start": 141,
+ "end": 165
+ }
+ },
+ "location": {
+ "startLine": 5,
+ "startColumn": 5,
+ "endLine": 7,
+ "endColumn": 16,
+ "start": 131,
+ "end": 254
+ },
+ "directiveLocation": {
+ "startLine": 5,
+ "startColumn": 15,
+ "endLine": 5,
+ "endColumn": 39,
+ "start": 141,
+ "end": 165
+ },
+ "children": [
+ {
+ "type": "Slot",
+ "name": "slot",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "slotName": "slotname1",
+ "location": {
+ "startLine": 6,
+ "startColumn": 9,
+ "endLine": 6,
+ "endColumn": 72,
+ "start": 175,
+ "end": 238,
+ "startTag": {
+ "startLine": 6,
+ "startColumn": 9,
+ "endLine": 6,
+ "endColumn": 65,
+ "start": 175,
+ "end": 231
+ },
+ "endTag": {
+ "startLine": 6,
+ "startColumn": 65,
+ "endLine": 6,
+ "endColumn": 72,
+ "start": 231,
+ "end": 238
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "name",
+ "value": {
+ "type": "Literal",
+ "value": "slotname1"
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 15,
+ "endLine": 6,
+ "endColumn": 31,
+ "start": 181,
+ "end": 197
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "SlotBind",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 17,
+ "name": "slot1VariantData",
+ "location": {
+ "startLine": 6,
+ "startColumn": 32,
+ "endLine": 6,
+ "endColumn": 64,
+ "start": 198,
+ "end": 230
+ }
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 32,
+ "endLine": 6,
+ "endColumn": 64,
+ "start": 198,
+ "end": 230
+ }
+ }
+ ],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/expected.js
new file mode 100644
index 0000000000..32f3808673
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/expected.js
@@ -0,0 +1,39 @@
+import { registerTemplate } from "lwc";
+const stc0 = {
+ attrs: {
+ name: "slotname1",
+ },
+ key: 1,
+};
+const stc1 = [];
+const stc2 = {
+ name: "slotname1",
+};
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const { s: api_slot, fr: api_fragment } = $api;
+ return [
+ $cmp.showStandard
+ ? api_fragment(0, api_slot("slotname1", stc0, stc1, $slotset), 0)
+ : $cmp.showVariant
+ ? api_fragment(
+ 0,
+ api_slot(
+ "slotname1",
+ {
+ attrs: stc2,
+ key: 2,
+ slotData: $cmp.slot1VariantData,
+ },
+ stc1,
+ $slotset
+ ),
+ 0
+ )
+ : null,
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.slots = ["slotname1"];
+tmpl.stylesheets = [];
+tmpl.renderMode = "light";
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/mixed-slot-types/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/actual.html
new file mode 100644
index 0000000000..5d97bdb0fe
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/actual.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/ast.json
new file mode 100644
index 0000000000..7751261dc1
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/ast.json
@@ -0,0 +1,277 @@
+{
+ "root": {
+ "type": "Root",
+ "location": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 8,
+ "endColumn": 12,
+ "start": 0,
+ "end": 299,
+ "startTag": {
+ "startLine": 1,
+ "startColumn": 1,
+ "endLine": 1,
+ "endColumn": 35,
+ "start": 0,
+ "end": 34
+ },
+ "endTag": {
+ "startLine": 8,
+ "startColumn": 1,
+ "endLine": 8,
+ "endColumn": 12,
+ "start": 288,
+ "end": 299
+ }
+ },
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "RenderMode",
+ "value": {
+ "type": "Literal",
+ "value": "light"
+ },
+ "location": {
+ "startLine": 1,
+ "startColumn": 11,
+ "endLine": 1,
+ "endColumn": 34,
+ "start": 10,
+ "end": 33
+ }
+ }
+ ],
+ "children": [
+ {
+ "type": "IfBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 13,
+ "name": "showStandard",
+ "location": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 36,
+ "start": 49,
+ "end": 70
+ }
+ },
+ "location": {
+ "startLine": 2,
+ "startColumn": 5,
+ "endLine": 4,
+ "endColumn": 16,
+ "start": 39,
+ "end": 159
+ },
+ "directiveLocation": {
+ "startLine": 2,
+ "startColumn": 15,
+ "endLine": 2,
+ "endColumn": 36,
+ "start": 49,
+ "end": 70
+ },
+ "children": [
+ {
+ "type": "Slot",
+ "name": "slot",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "slotName": "slotname1",
+ "location": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 72,
+ "start": 80,
+ "end": 143,
+ "startTag": {
+ "startLine": 3,
+ "startColumn": 9,
+ "endLine": 3,
+ "endColumn": 65,
+ "start": 80,
+ "end": 136
+ },
+ "endTag": {
+ "startLine": 3,
+ "startColumn": 65,
+ "endLine": 3,
+ "endColumn": 72,
+ "start": 136,
+ "end": 143
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "name",
+ "value": {
+ "type": "Literal",
+ "value": "slotname1"
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 15,
+ "endLine": 3,
+ "endColumn": 31,
+ "start": 86,
+ "end": 102
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "SlotBind",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 17,
+ "name": "slot1VariantData",
+ "location": {
+ "startLine": 3,
+ "startColumn": 32,
+ "endLine": 3,
+ "endColumn": 64,
+ "start": 103,
+ "end": 135
+ }
+ },
+ "location": {
+ "startLine": 3,
+ "startColumn": 32,
+ "endLine": 3,
+ "endColumn": 64,
+ "start": 103,
+ "end": 135
+ }
+ }
+ ],
+ "listeners": [],
+ "children": []
+ }
+ ],
+ "else": {
+ "type": "ElseifBlock",
+ "condition": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 12,
+ "name": "showVariant",
+ "location": {
+ "startLine": 5,
+ "startColumn": 15,
+ "endLine": 5,
+ "endColumn": 39,
+ "start": 174,
+ "end": 198
+ }
+ },
+ "location": {
+ "startLine": 5,
+ "startColumn": 5,
+ "endLine": 7,
+ "endColumn": 16,
+ "start": 164,
+ "end": 287
+ },
+ "directiveLocation": {
+ "startLine": 5,
+ "startColumn": 15,
+ "endLine": 5,
+ "endColumn": 39,
+ "start": 174,
+ "end": 198
+ },
+ "children": [
+ {
+ "type": "Slot",
+ "name": "slot",
+ "namespace": "http://www.w3.org/1999/xhtml",
+ "slotName": "slotname1",
+ "location": {
+ "startLine": 6,
+ "startColumn": 9,
+ "endLine": 6,
+ "endColumn": 72,
+ "start": 208,
+ "end": 271,
+ "startTag": {
+ "startLine": 6,
+ "startColumn": 9,
+ "endLine": 6,
+ "endColumn": 65,
+ "start": 208,
+ "end": 264
+ },
+ "endTag": {
+ "startLine": 6,
+ "startColumn": 65,
+ "endLine": 6,
+ "endColumn": 72,
+ "start": 264,
+ "end": 271
+ }
+ },
+ "attributes": [
+ {
+ "type": "Attribute",
+ "name": "name",
+ "value": {
+ "type": "Literal",
+ "value": "slotname1"
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 15,
+ "endLine": 6,
+ "endColumn": 31,
+ "start": 214,
+ "end": 230
+ }
+ }
+ ],
+ "properties": [],
+ "directives": [
+ {
+ "type": "Directive",
+ "name": "SlotBind",
+ "value": {
+ "type": "Identifier",
+ "start": 1,
+ "end": 17,
+ "name": "slot1VariantData",
+ "location": {
+ "startLine": 6,
+ "startColumn": 32,
+ "endLine": 6,
+ "endColumn": 64,
+ "start": 231,
+ "end": 263
+ }
+ },
+ "location": {
+ "startLine": 6,
+ "startColumn": 32,
+ "endLine": 6,
+ "endColumn": 64,
+ "start": 231,
+ "end": 263
+ }
+ }
+ ],
+ "listeners": [],
+ "children": []
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/expected.js
new file mode 100644
index 0000000000..ff7c34287a
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/expected.js
@@ -0,0 +1,46 @@
+import { registerTemplate } from "lwc";
+const stc0 = {
+ name: "slotname1",
+};
+const stc1 = [];
+function tmpl($api, $cmp, $slotset, $ctx) {
+ const { s: api_slot, fr: api_fragment } = $api;
+ return [
+ $cmp.showStandard
+ ? api_fragment(
+ 0,
+ api_slot(
+ "slotname1",
+ {
+ attrs: stc0,
+ key: 1,
+ slotData: $cmp.slot1VariantData,
+ },
+ stc1,
+ $slotset
+ ),
+ 0
+ )
+ : $cmp.showVariant
+ ? api_fragment(
+ 0,
+ api_slot(
+ "slotname1",
+ {
+ attrs: stc0,
+ key: 2,
+ slotData: $cmp.slot1VariantData,
+ },
+ stc1,
+ $slotset
+ ),
+ 0
+ )
+ : null,
+ ];
+ /*LWC compiler vX.X.X*/
+}
+export default registerTemplate(tmpl);
+tmpl.slots = ["slotname1"];
+tmpl.stylesheets = [];
+tmpl.renderMode = "light";
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/metadata.json
new file mode 100644
index 0000000000..51ec5f799c
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/if-block/valid/same-slot-types/metadata.json
@@ -0,0 +1,3 @@
+{
+ "warnings": []
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/actual.html b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/actual.html
new file mode 100644
index 0000000000..5c9248dce2
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/actual.html
@@ -0,0 +1,4 @@
+
+ Regular Slot
+ Scoped Slot
+
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/ast.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/ast.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/ast.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/config.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/config.json
new file mode 100644
index 0000000000..089a290bd4
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/config.json
@@ -0,0 +1,3 @@
+{
+ "enableScopedSlots": true
+}
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/expected.js b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/expected.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/metadata.json b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/metadata.json
new file mode 100644
index 0000000000..ff3294afac
--- /dev/null
+++ b/packages/@lwc/template-compiler/src/__tests__/fixtures/scoped-slots/invalid/slot-bind/mixed-slot-alt/metadata.json
@@ -0,0 +1,15 @@
+{
+ "warnings": [
+ {
+ "code": 1173,
+ "message": "LWC1173: Mixing slot types disallowed for same (default) slot.",
+ "level": 1,
+ "location": {
+ "line": 3,
+ "column": 5,
+ "start": 69,
+ "length": 49
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/@lwc/template-compiler/src/codegen/codegen.ts b/packages/@lwc/template-compiler/src/codegen/codegen.ts
index 4a17204c89..72b767c9a1 100644
--- a/packages/@lwc/template-compiler/src/codegen/codegen.ts
+++ b/packages/@lwc/template-compiler/src/codegen/codegen.ts
@@ -258,6 +258,9 @@ export default class CodeGen {
return this._renderApiCall(RENDER_APIS.scopedFragId, [id]);
}
+ /**
+ * Generates childs vnodes when slot content is static.
+ */
getSlot(slotName: string, data: t.ObjectExpression, children: t.Expression) {
this.slotNames.add(slotName);
@@ -269,6 +272,13 @@ export default class CodeGen {
]);
}
+ /**
+ * Generates a factory function that inturn generates child vnodes for scoped slot content.
+ */
+ getScopedSlotFactory(callback: t.FunctionExpression, slotName: t.SimpleLiteral) {
+ return this._renderApiCall(RENDER_APIS.scopedSlotFactory, [callback, slotName]);
+ }
+
genTabIndex(children: [t.Expression]) {
return this._renderApiCall(RENDER_APIS.tabindex, children);
}
@@ -358,10 +368,6 @@ export default class CodeGen {
);
}
- getScopedSlotFactory(callback: t.FunctionExpression, slotName: t.SimpleLiteral) {
- return this._renderApiCall(RENDER_APIS.scopedSlotFactory, [callback, slotName]);
- }
-
private _renderApiCall(
primitive: RenderPrimitiveDefinition,
params: t.Expression[]
diff --git a/packages/@lwc/template-compiler/src/parser/index.ts b/packages/@lwc/template-compiler/src/parser/index.ts
index 56f9f2c184..2237a89e8f 100644
--- a/packages/@lwc/template-compiler/src/parser/index.ts
+++ b/packages/@lwc/template-compiler/src/parser/index.ts
@@ -1219,21 +1219,24 @@ function parseSlot(
ctx.addSeenSlot(name);
if (alreadySeen) {
- // If slot name has been shared with a prior scoped slot, throw an error.
// Scoped slots do not allow duplicate or mixed slots
// https://rfcs.lwc.dev/rfcs/lwc/0118-scoped-slots-light-dom#restricting-ambigious-bindings
// https://rfcs.lwc.dev/rfcs/lwc/0118-scoped-slots-light-dom#invalid-usages
+ // Note: ctx.seenScopedSlots is not "if" context aware and it does not need to be.
+ // It is only responsible to determine if a scoped slot with the same name has been seen prior.
if (ctx.seenScopedSlots.has(name)) {
// Differentiate between mixed type or duplicate scoped slot
const errorInfo = isScopedSlot
- ? ParserDiagnostics.NO_DUPLICATE_SCOPED_SLOT
- : ParserDiagnostics.NO_MIXED_SLOT_TYPES;
+ ? ParserDiagnostics.NO_DUPLICATE_SCOPED_SLOT // error
+ : ParserDiagnostics.NO_MIXED_SLOT_TYPES; // error
ctx.throwAtLocation(errorInfo, location, [name === '' ? 'default' : `name="${name}"`]);
} else {
+ // Differentiate between mixed type or duplicate standard slot
+ const errorInfo = isScopedSlot
+ ? ParserDiagnostics.NO_MIXED_SLOT_TYPES // error
+ : ParserDiagnostics.NO_DUPLICATE_SLOTS; // warning
// for standard slots, preserve old behavior of warnings
- ctx.warnAtLocation(ParserDiagnostics.NO_DUPLICATE_SLOTS, location, [
- name === '' ? 'default' : `name="${name}"`,
- ]);
+ ctx.warnAtLocation(errorInfo, location, [name === '' ? 'default' : `name="${name}"`]);
}
} else if (!isScopedSlot && isInIteration(ctx)) {
// Scoped slots are allowed to be placed in iteration blocks
diff --git a/packages/@lwc/template-compiler/src/parser/parser.ts b/packages/@lwc/template-compiler/src/parser/parser.ts
index a07d6386cb..1229bac892 100644
--- a/packages/@lwc/template-compiler/src/parser/parser.ts
+++ b/packages/@lwc/template-compiler/src/parser/parser.ts
@@ -80,6 +80,9 @@ export default class ParserCtx {
readonly seenIds: Set = new Set();
readonly seenSlots: Set = new Set();
+ /**
+ * This set is not aware of if-elseif-else blocks.
+ */
readonly seenScopedSlots: Set = new Set();
/**
diff --git a/packages/@lwc/template-compiler/src/shared/ast.ts b/packages/@lwc/template-compiler/src/shared/ast.ts
index 2fe6e75c11..d9af63fd35 100644
--- a/packages/@lwc/template-compiler/src/shared/ast.ts
+++ b/packages/@lwc/template-compiler/src/shared/ast.ts
@@ -45,7 +45,6 @@ import {
ElementDirective,
RootDirective,
SlotBindDirective,
- /* SlotDataDirective, */
ScopedSlotContent,
SlotDataDirective,
} from './types';
diff --git a/scripts/bundlesize/bundlesize.config.json b/scripts/bundlesize/bundlesize.config.json
index c5cafa216e..d696800e7f 100644
--- a/scripts/bundlesize/bundlesize.config.json
+++ b/scripts/bundlesize/bundlesize.config.json
@@ -2,7 +2,7 @@
"files": [
{
"path": "packages/lwc/dist/engine-dom/umd/es2017/engine-dom.min.js",
- "maxSize": "18.6KB",
+ "maxSize": "20KB",
"compression": "gzip"
},
{