Skip to content

Commit 8530d0e

Browse files
committed
fix(platform-browser): IsolatedShadowDom encapsulation
Implement IsolatedStyleScopeService. Refactor IsolatedShadowDom implementation to fix various bugs. Uses native slot instead of ng-content.
1 parent 8f3fdc3 commit 8530d0e

File tree

27 files changed

+795
-145
lines changed

27 files changed

+795
-145
lines changed

adev/src/content/guide/routing/data-resolvers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,11 @@ export class App {
205205
map(event => {
206206
if (event instanceof NavigationError) {
207207
this.lastFailedUrl.set(event.url);
208-
208+
209209
if (event.error) {
210210
console.error('Navigation error', event.error)
211211
}
212-
212+
213213
return 'Navigation failed. Please try again.';
214214
}
215215
return '';

goldens/public-api/compiler-cli/error_code.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export enum ErrorCode {
7878
INLINE_TYPE_CTOR_REQUIRED = 8901,
7979
INTERPOLATED_SIGNAL_NOT_INVOKED = 8109,
8080
INVALID_BANANA_IN_BOX = 8101,
81+
ISOLATED_SHADOW_DOM_INVALID_CONTENT_PROJECTION = 2027,
8182
LET_USED_BEFORE_DEFINITION = 8016,
8283
LOCAL_COMPILATION_UNRESOLVED_CONST = 11001,
8384
LOCAL_COMPILATION_UNSUPPORTED_EXPRESSION = 11003,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"dist/main.js": 108611,
3-
"dist/polyfills.js": 34169,
4-
"dist/lazy.routes-[hash].js": 361
2+
"dist/main.js": 113764,
3+
"dist/polyfills.js": 34585,
4+
"dist/lazy.routes-[hash].js": 348
55
}

integration/defer/size.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"dist/main.js": 12709,
2+
"dist/main.js": 16485,
33
"dist/polyfills.js": 35677,
4-
"dist/defer.component-[hash].js": 345
4+
"dist/defer.component-[hash].js": 331
55
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"dist/main.js": 97227,
2+
"dist/main.js": 102215,
33
"dist/polyfills.js": 35677,
4-
"dist/browser-[hash].js": 63949,
5-
"dist/open-close.component-[hash].js": 1218
4+
"dist/browser-[hash].js": 64236,
5+
"dist/open-close.component-[hash].js": 1189
66
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"dist/main.js": 153915,
3-
"dist/polyfills.js": 34023,
4-
"dist/open-close.component-[hash].js": 1190
2+
"dist/main.js": 159053,
3+
"dist/polyfills.js": 35677,
4+
"dist/open-close.component-[hash].js": 1131
55
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"dist/browser/main-[hash].js": 227093,
3-
"dist/browser/polyfills-[hash].js": 34544,
2+
"dist/browser/main-[hash].js": 234529,
3+
"dist/browser/polyfills-[hash].js": 35677,
44
"dist/browser/event-dispatch-contract.min.js": 476
55
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"dist/main.js": 89237,
2+
"dist/main.js": 97201,
33
"dist/polyfills.js": 35677
44
}

packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,24 @@ export class ComponentDecoratorHandler
908908
}
909909
}
910910

911+
// Check for ng-content in IsolatedShadowDom components
912+
if (encapsulation === ViewEncapsulation.ExperimentalIsolatedShadowDom) {
913+
const contentNode = findContentNode(template.nodes);
914+
if (contentNode !== null) {
915+
if (diagnostics === undefined) {
916+
diagnostics = [];
917+
}
918+
diagnostics.push(
919+
makeDiagnostic(
920+
ErrorCode.ISOLATED_SHADOW_DOM_INVALID_CONTENT_PROJECTION,
921+
component.get('template') ?? node.name,
922+
`ng-content projection is not supported with ViewEncapsulation.ExperimentalIsolatedShadowDom. ` +
923+
`Use native <slot> elements instead. Content will remain in the light DOM and be projected via slots.`,
924+
),
925+
);
926+
}
927+
}
928+
911929
// If inline styles were preprocessed use those
912930
let inlineStyles: string[] | null = null;
913931
if (this.preanalyzeStylesCache.has(node)) {
@@ -2637,3 +2655,24 @@ function validateStandaloneImports(
26372655
function isDefaultImport(node: ts.ImportDeclaration): boolean {
26382656
return node.importClause !== undefined && node.importClause.namedBindings === undefined;
26392657
}
2658+
2659+
/**
2660+
* Recursively searches through template nodes to find a Content node (ng-content).
2661+
* Returns the first Content node found, or null if none exist.
2662+
*/
2663+
function findContentNode(nodes: any[]): any | null {
2664+
for (const node of nodes) {
2665+
// Check if this is a Content node (ng-content)
2666+
if (node.name === 'ng-content') {
2667+
return node;
2668+
}
2669+
// Recursively check children
2670+
if (node.children && node.children.length > 0) {
2671+
const found = findContentNode(node.children);
2672+
if (found !== null) {
2673+
return found;
2674+
}
2675+
}
2676+
}
2677+
return null;
2678+
}

packages/compiler-cli/src/ngtsc/diagnostics/src/error_code.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ export enum ErrorCode {
184184
*/
185185
COMPONENT_ANIMATIONS_CONFLICT = 2027,
186186

187+
/**
188+
* Raised when a component with `ViewEncapsulation.ExperimentalIsolatedShadowDom` uses `<ng-content>`.
189+
* ExperimentalIsolatedShadowDom components must use native `<slot>` elements instead.
190+
*/
191+
ISOLATED_SHADOW_DOM_INVALID_CONTENT_PROJECTION = 2028,
192+
187193
SYMBOL_NOT_EXPORTED = 3001,
188194
/**
189195
* Raised when a relationship between directives and/or pipes would cause a cyclic import to be

0 commit comments

Comments
 (0)