Skip to content

Commit

Permalink
feat(template-compiler): warning for slot attribute not at the top level
Browse files Browse the repository at this point in the history
  • Loading branch information
cardoso committed Oct 26, 2024
1 parent cd41384 commit 15e7602
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/@lwc/engine-server/src/__tests__/fixtures.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ async function compileFixture({ input, dirname }: { input: string; dirname: stri
message.includes('LWC1187') ||
// TODO [#4497]: stop warning on duplicate slots or disallow them entirely (LWC1137 is duplicate slots)
message.includes('LWC1137') ||
message.includes('LWC1201') ||
message.includes('-h-t-m-l') ||
code === 'CIRCULAR_DEPENDENCY';
if (!shouldIgnoreWarning) {
Expand Down
2 changes: 1 addition & 1 deletion packages/@lwc/errors/src/compiler/error-info/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
/**
* Next error code: 1201
* Next error code: 1202
*/

export * from './compiler';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -939,4 +939,12 @@ export const ParserDiagnostics = {
level: DiagnosticLevel.Error,
url: '',
},

SLOT_ATTRIBUTE_NOT_AT_TOP_LEVEL: {
code: 1201,
message:
'Invalid slot attribute usage inside {0}. The slot attribute will likely be ignored.',
level: DiagnosticLevel.Warning,
url: '',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<template>
<x-inner>
<div>
<span slot="foo">I am the foo slot</span>
</div>
</x-inner>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
{
"root": {
"type": "Root",
"location": {
"startLine": 1,
"startColumn": 1,
"endLine": 7,
"endColumn": 12,
"start": 0,
"end": 134,
"startTag": {
"startLine": 1,
"startColumn": 1,
"endLine": 1,
"endColumn": 11,
"start": 0,
"end": 10
},
"endTag": {
"startLine": 7,
"startColumn": 1,
"endLine": 7,
"endColumn": 12,
"start": 123,
"end": 134
}
},
"directives": [],
"children": [
{
"type": "Component",
"name": "x-inner",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
"startLine": 2,
"startColumn": 5,
"endLine": 6,
"endColumn": 15,
"start": 15,
"end": 122,
"startTag": {
"startLine": 2,
"startColumn": 5,
"endLine": 2,
"endColumn": 14,
"start": 15,
"end": 24
},
"endTag": {
"startLine": 6,
"startColumn": 5,
"endLine": 6,
"endColumn": 15,
"start": 112,
"end": 122
}
},
"attributes": [],
"properties": [],
"directives": [],
"listeners": [],
"children": [
{
"type": "Element",
"name": "div",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
"startLine": 3,
"startColumn": 9,
"endLine": 5,
"endColumn": 15,
"start": 33,
"end": 107,
"startTag": {
"startLine": 3,
"startColumn": 9,
"endLine": 3,
"endColumn": 14,
"start": 33,
"end": 38
},
"endTag": {
"startLine": 5,
"startColumn": 9,
"endLine": 5,
"endColumn": 15,
"start": 101,
"end": 107
}
},
"attributes": [],
"properties": [],
"directives": [],
"listeners": [],
"children": [
{
"type": "Element",
"name": "span",
"namespace": "http://www.w3.org/1999/xhtml",
"location": {
"startLine": 4,
"startColumn": 13,
"endLine": 4,
"endColumn": 54,
"start": 51,
"end": 92,
"startTag": {
"startLine": 4,
"startColumn": 13,
"endLine": 4,
"endColumn": 30,
"start": 51,
"end": 68
},
"endTag": {
"startLine": 4,
"startColumn": 47,
"endLine": 4,
"endColumn": 54,
"start": 85,
"end": 92
}
},
"attributes": [
{
"type": "Attribute",
"name": "slot",
"value": {
"type": "Literal",
"value": "foo"
},
"location": {
"startLine": 4,
"startColumn": 19,
"endLine": 4,
"endColumn": 29,
"start": 57,
"end": 67
}
}
],
"properties": [],
"directives": [],
"listeners": [],
"children": [
{
"type": "Text",
"raw": "I am the foo slot",
"value": {
"type": "Literal",
"value": "I am the foo slot"
},
"location": {
"startLine": 4,
"startColumn": 30,
"endLine": 4,
"endColumn": 47,
"start": 68,
"end": 85
}
}
]
}
]
}
]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import _implicitStylesheets from "./top-level-warning.css";
import _implicitScopedStylesheets from "./top-level-warning.scoped.css?scoped=true";
import _xInner from "x/inner";
import { freezeTemplate, registerTemplate } from "lwc";
const stc0 = {
key: 0,
};
const stc1 = {
key: 1,
};
const stc2 = {
slotAssignment: "foo",
key: 2,
};
function tmpl($api, $cmp, $slotset, $ctx) {
const { t: api_text, h: api_element, c: api_custom_element } = $api;
return [
api_custom_element("x-inner", _xInner, stc0, [
api_element("div", stc1, [
api_element("span", stc2, [api_text("I am the foo slot")]),
]),
]),
];
/*LWC compiler vX.X.X*/
}
export default registerTemplate(tmpl);
tmpl.stylesheets = [];
tmpl.stylesheetToken = "lwc-2vrd1nfb7kv";
tmpl.legacyStylesheetToken = "x-top-level-warning_top-level-warning";
if (_implicitStylesheets) {
tmpl.stylesheets.push.apply(tmpl.stylesheets, _implicitStylesheets);
}
if (_implicitScopedStylesheets) {
tmpl.stylesheets.push.apply(tmpl.stylesheets, _implicitScopedStylesheets);
}
freezeTemplate(tmpl);
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"warnings": [
{
"code": 1201,
"message": "LWC1201: Invalid slot attribute usage inside <div>. The slot attribute will likely be ignored.",
"level": 2,
"location": {
"line": 4,
"column": 19,
"start": 57,
"length": 10
}
}
]
}
17 changes: 17 additions & 0 deletions packages/@lwc/template-compiler/src/parser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,19 @@ function parseElement(
parse5ElmLocation
);

const slotAttr = parsedAttr.get('slot');
if (slotAttr && ignoresSlotAttributeInChild(parentNode)) {
ctx.warnAtLocation(ParserDiagnostics.SLOT_ATTRIBUTE_NOT_AT_TOP_LEVEL, slotAttr.location, [
ast.isElement(parentNode)
? `<${parentNode.name}>`
: ast.isForEach(parentNode)
? 'for:each'
: ast.isForOf(parentNode)
? 'for:of'
: 'slot',
]);
}

if (element) {
applyHandlers(ctx, parsedAttr, element);
applyKey(ctx, parsedAttr, element);
Expand Down Expand Up @@ -1830,3 +1843,7 @@ function getForEachParent(ctx: ParserCtx): ForEach | null {
function isInIteratorElement(ctx: ParserCtx): boolean {
return !!(getForOfParent(ctx) || getForEachParent(ctx));
}

function ignoresSlotAttributeInChild(p: ParentNode) {
return ast.isElement(p) || ast.isForEach(p) || ast.isForOf(p) || ast.isSlot(p);
}

0 comments on commit 15e7602

Please sign in to comment.