Skip to content
Closed
15 changes: 15 additions & 0 deletions goldens/public-api/core/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ export function createComponent<C>(component: Type<C>, options: {
projectableNodes?: Node[][];
directives?: (Type<unknown> | DirectiveWithBindings<unknown>)[];
bindings?: Binding[];
onError?: (error: Error, details: ErrorDetails) => void;
}): ComponentRef<C>;

// @public
Expand Down Expand Up @@ -709,10 +710,22 @@ export type EnvironmentProviders = {
ɵbrand: 'EnvironmentProviders';
};

// @public
export interface ErrorDetails {
readonly boundary?: {
readonly type: Type<unknown>;
readonly reset: () => void;
};
readonly caughtBy?: Function;
readonly declarationInstance: unknown;
readonly declarationType: Type<unknown>;
}

// @public
export class ErrorHandler {
// (undocumented)
handleError(error: any): void;
onViewError?(error: Error, details: ErrorDetails): void;
}

// @public
Expand Down Expand Up @@ -2098,10 +2111,12 @@ export abstract class ViewContainerRef {
projectableNodes?: Node[][];
directives?: (Type<unknown> | DirectiveWithBindings<unknown>)[];
bindings?: Binding[];
onError?: (error: Error, context: ErrorDetails) => void;
}): ComponentRef<C>;
abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, options?: {
index?: number;
injector?: Injector;
onError?: (error: Error, details: ErrorDetails) => void;
}): EmbeddedViewRef<C>;
abstract createEmbeddedView<C>(templateRef: TemplateRef<C>, context?: C, index?: number): EmbeddedViewRef<C>;
abstract detach(index?: number): ViewRef | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/****************************************************************************************************
* PARTIAL FILE: basic.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error {
Fallback Content
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error {
Fallback Content
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: basic.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: error_declaration.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error (let err) {
Error: {{err.message}}
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error (let err) {
Error: {{err.message}}
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: error_declaration.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: retry_alias.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error (let err, retry = $reset) {
<button (click)="retry()">Retry</button>
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error (let err, retry = $reset) {
<button (click)="retry()">Retry</button>
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: retry_alias.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: retry_implicit.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error {
<button (click)="$reset()">Retry</button>
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error {
<button (click)="$reset()">Retry</button>
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: retry_implicit.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: when_condition.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error (let err; when err.message === '404') {
Not Found
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error (let err; when err.message === '404') {
Not Found
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: when_condition.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: multiple_error_blocks.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Main Content
} @error (let err; when err.message === '404') {
Not Found
} @error (let err) {
Generic Error
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Main Content
} @error (let err; when err.message === '404') {
Not Found
} @error (let err) {
Generic Error
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: multiple_error_blocks.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

/****************************************************************************************************
* PARTIAL FILE: nested.js
****************************************************************************************************/
import { Component } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComponent {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "0.0.0-PLACEHOLDER", type: TestComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
@boundary {
Outer Main
@boundary {
Inner Main
} @error {
Inner Fallback
}
} @error {
Outer Fallback
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComponent, decorators: [{
type: Component,
args: [{
template: `
@boundary {
Outer Main
@boundary {
Inner Main
} @error {
Inner Fallback
}
} @error {
Outer Fallback
}
`
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: nested.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComponent {
static ɵfac: i0.ɵɵFactoryDeclaration<TestComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TestComponent, "ng-component", never, {}, {}, never, never, true, never>;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"$schema": "../../test_case_schema.json",
"cases": [
{
"description": "should generate boundary and error blocks",
"inputFiles": ["basic.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions",
"files": ["basic.js"]
}
]
},
{
"description": "should support let declaration of the error",
"inputFiles": ["error_declaration.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions for error declaration",
"files": ["error_declaration.js"]
}
]
},
{
"description": "should support retry function alias",
"inputFiles": ["retry_alias.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions for retry alias",
"files": ["retry_alias.js"]
}
]
},
{
"description": "should support retry implicitly",
"inputFiles": ["retry_implicit.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions",
"files": ["retry_implicit.js"]
}
]
},
{
"description": "should support when conditions",
"inputFiles": ["when_condition.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions for when condition",
"files": ["when_condition.js"]
}
]
},
{
"description": "should support multiple error blocks",
"inputFiles": ["multiple_error_blocks.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions for multiple error blocks",
"files": ["multiple_error_blocks.js"]
}
]
},
{
"description": "should support nested boundaries",
"inputFiles": ["nested.ts"],
"expectations": [
{
"failureMessage": "Incorrect boundary instructions for nested boundaries",
"files": ["nested.js"]
}
]
}
]
}
Loading
Loading