
The main use case for the generated source maps is to give errors a meaningful context in terms of the original source that the user wrote. Related changes that are included in this commit: * renamed virtual folders used for jit: * ng://<module type>/module.ngfactory.js * ng://<module type>/<comp type>.ngfactory.js * ng://<module type>/<comp type>.html (for inline templates) * error logging: * all errors that happen in templates are logged from the place of the nearest element. * instead of logging error messages and stacks separately, we log the actual error. This is needed so that browsers apply source maps to the stack correctly. * error type and error is logged as one log entry. Note that long-stack-trace zone has a bug that disables source maps for stack traces, see https://github.com/angular/zone.js/issues/661. BREAKING CHANGE: - DebugNode.source no more returns the source location of a node. Closes 14013
52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {ERROR_DEBUG_CONTEXT, ERROR_LOGGER, getDebugContext} from '../errors';
|
|
import {DebugContext, ViewState} from './types';
|
|
|
|
export function expressionChangedAfterItHasBeenCheckedError(
|
|
context: DebugContext, oldValue: any, currValue: any, isFirstCheck: boolean): Error {
|
|
let msg =
|
|
`ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
|
if (isFirstCheck) {
|
|
msg +=
|
|
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
|
` Has it been created in a change detection hook ?`;
|
|
}
|
|
return viewDebugError(msg, context);
|
|
}
|
|
|
|
export function viewWrappedDebugError(err: any, context: DebugContext): Error {
|
|
if (!(err instanceof Error)) {
|
|
// errors that are not Error instances don't have a stack,
|
|
// so it is ok to wrap them into a new Error object...
|
|
err = new Error(err.toString());
|
|
}
|
|
_addDebugContext(err, context);
|
|
return err;
|
|
}
|
|
|
|
export function viewDebugError(msg: string, context: DebugContext): Error {
|
|
const err = new Error(msg);
|
|
_addDebugContext(err, context);
|
|
return err;
|
|
}
|
|
|
|
function _addDebugContext(err: Error, context: DebugContext) {
|
|
(err as any)[ERROR_DEBUG_CONTEXT] = context;
|
|
(err as any)[ERROR_LOGGER] = context.logError.bind(context);
|
|
}
|
|
|
|
export function isViewDebugError(err: Error): boolean {
|
|
return !!getDebugContext(err);
|
|
}
|
|
|
|
export function viewDestroyedError(action: string): Error {
|
|
return new Error(`ViewDestroyedError: Attempt to use a destroyed view: ${action}`);
|
|
}
|