parent
32157115da
commit
2fce701ced
|
@ -15,8 +15,8 @@ import {QueryList} from '../linker';
|
||||||
import {Sanitizer} from '../sanitization/security';
|
import {Sanitizer} from '../sanitization/security';
|
||||||
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
|
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect';
|
||||||
import {noop} from '../util/noop';
|
import {noop} from '../util/noop';
|
||||||
|
|
||||||
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
|
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
|
||||||
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
|
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
|
||||||
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
|
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
|
||||||
|
@ -956,6 +956,9 @@ export function elementProperty<T>(
|
||||||
if (inputData && (dataValue = inputData[propName])) {
|
if (inputData && (dataValue = inputData[propName])) {
|
||||||
setInputsForProperty(viewData, dataValue, value);
|
setInputsForProperty(viewData, dataValue, value);
|
||||||
if (isComponent(tNode)) markDirtyIfOnPush(viewData, index + HEADER_OFFSET);
|
if (isComponent(tNode)) markDirtyIfOnPush(viewData, index + HEADER_OFFSET);
|
||||||
|
if (ngDevMode && tNode.type === TNodeType.Element) {
|
||||||
|
setNgReflectProperties(element as RElement, propName, value);
|
||||||
|
}
|
||||||
} else if (tNode.type === TNodeType.Element) {
|
} else if (tNode.type === TNodeType.Element) {
|
||||||
const renderer = getRenderer();
|
const renderer = getRenderer();
|
||||||
// It is assumed that the sanitizer is only added when the compiler determines that the property
|
// It is assumed that the sanitizer is only added when the compiler determines that the property
|
||||||
|
@ -1025,6 +1028,15 @@ function setInputsForProperty(viewData: LViewData, inputs: PropertyAliasValue, v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setNgReflectProperties(element: RElement, propName: string, value: any) {
|
||||||
|
const renderer = getRenderer() as ProceduralRenderer3;
|
||||||
|
const isProcedural = isProceduralRenderer(renderer);
|
||||||
|
const attrName = normalizeDebugBindingName(propName);
|
||||||
|
const debugValue = normalizeDebugBindingValue(value);
|
||||||
|
isProcedural ? renderer.setAttribute(element, attrName, debugValue) :
|
||||||
|
element.setAttribute(attrName, debugValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consolidates all inputs or outputs of all directives on this logical node.
|
* Consolidates all inputs or outputs of all directives on this logical node.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function normalizeDebugBindingName(name: string) {
|
||||||
|
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
||||||
|
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
||||||
|
return `ng-reflect-${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||||
|
|
||||||
|
function camelCaseToDashCase(input: string): string {
|
||||||
|
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeDebugBindingValue(value: any): string {
|
||||||
|
try {
|
||||||
|
// Limit the size of the value as otherwise the DOM just gets polluted.
|
||||||
|
return value != null ? value.toString().slice(0, 30) : value;
|
||||||
|
} catch (e) {
|
||||||
|
return '[ERROR] Exception while trying to serialize the value';
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,14 +18,13 @@ import {NgModuleRef} from '../linker/ng_module_factory';
|
||||||
import {Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '../render/api';
|
import {Renderer2, RendererFactory2, RendererStyleFlags2, RendererType2} from '../render/api';
|
||||||
import {Sanitizer} from '../sanitization/security';
|
import {Sanitizer} from '../sanitization/security';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
import {tokenKey} from '../view/util';
|
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../util/ng_reflect';
|
||||||
|
|
||||||
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors';
|
||||||
import {resolveDep} from './provider';
|
import {resolveDep} from './provider';
|
||||||
import {dirtyParentQueries, getQueryValue} from './query';
|
import {dirtyParentQueries, getQueryValue} from './query';
|
||||||
import {createInjector, createNgModuleRef, getComponentViewDefinitionFactory} from './refs';
|
import {createInjector, createNgModuleRef, getComponentViewDefinitionFactory} from './refs';
|
||||||
import {ArgumentType, BindingFlags, CheckType, DebugContext, ElementData, NgModuleDefinition, NodeDef, NodeFlags, NodeLogger, ProviderOverride, RootData, Services, ViewData, ViewDefinition, ViewState, asElementData, asPureExpressionData} from './types';
|
import {ArgumentType, BindingFlags, CheckType, DebugContext, ElementData, NgModuleDefinition, NodeDef, NodeFlags, NodeLogger, ProviderOverride, RootData, Services, ViewData, ViewDefinition, ViewState, asElementData, asPureExpressionData} from './types';
|
||||||
import {NOOP, isComponentView, renderNode, resolveDefinition, splitDepsDsl, viewParentEl} from './util';
|
import {NOOP, isComponentView, renderNode, resolveDefinition, splitDepsDsl, tokenKey, viewParentEl} from './util';
|
||||||
import {checkAndUpdateNode, checkAndUpdateView, checkNoChangesNode, checkNoChangesView, createComponentView, createEmbeddedView, createRootView, destroyView} from './view';
|
import {checkAndUpdateNode, checkAndUpdateView, checkNoChangesNode, checkNoChangesView, createComponentView, createEmbeddedView, createRootView, destroyView} from './view';
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,27 +466,6 @@ function debugCheckNoChangesNode(
|
||||||
(<any>checkNoChangesNode)(view, nodeDef, argStyle, ...values);
|
(<any>checkNoChangesNode)(view, nodeDef, argStyle, ...values);
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeDebugBindingName(name: string) {
|
|
||||||
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
||||||
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
|
||||||
return `ng-reflect-${name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
|
||||||
|
|
||||||
function camelCaseToDashCase(input: string): string {
|
|
||||||
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeDebugBindingValue(value: any): string {
|
|
||||||
try {
|
|
||||||
// Limit the size of the value as otherwise the DOM just gets polluted.
|
|
||||||
return value != null ? value.toString().slice(0, 30) : value;
|
|
||||||
} catch (e) {
|
|
||||||
return '[ERROR] Exception while trying to serialize the value';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextDirectiveWithBinding(view: ViewData, nodeIndex: number): number|null {
|
function nextDirectiveWithBinding(view: ViewData, nodeIndex: number): number|null {
|
||||||
for (let i = nodeIndex; i < view.def.nodes.length; i++) {
|
for (let i = nodeIndex; i < view.def.nodes.length; i++) {
|
||||||
const nodeDef = view.def.nodes[i];
|
const nodeDef = view.def.nodes[i];
|
||||||
|
|
|
@ -218,11 +218,11 @@ export function resetDOM() {
|
||||||
export function renderToHtml(
|
export function renderToHtml(
|
||||||
template: ComponentTemplate<any>, ctx: any, consts: number = 0, vars: number = 0,
|
template: ComponentTemplate<any>, ctx: any, consts: number = 0, vars: number = 0,
|
||||||
directives?: DirectiveTypesOrFactory | null, pipes?: PipeTypesOrFactory | null,
|
directives?: DirectiveTypesOrFactory | null, pipes?: PipeTypesOrFactory | null,
|
||||||
providedRendererFactory?: RendererFactory3 | null) {
|
providedRendererFactory?: RendererFactory3 | null, keepNgReflect = false) {
|
||||||
hostView = renderTemplate(
|
hostView = renderTemplate(
|
||||||
containerEl, template, consts, vars, ctx, providedRendererFactory || testRendererFactory,
|
containerEl, template, consts, vars, ctx, providedRendererFactory || testRendererFactory,
|
||||||
hostView, toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
|
hostView, toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
|
||||||
return toHtml(containerEl);
|
return toHtml(containerEl, keepNgReflect);
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDefs(
|
function toDefs(
|
||||||
|
@ -263,7 +263,7 @@ export function renderComponent<T>(type: ComponentType<T>, opts?: CreateComponen
|
||||||
/**
|
/**
|
||||||
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
||||||
*/
|
*/
|
||||||
export function toHtml<T>(componentOrElement: T | RElement): string {
|
export function toHtml<T>(componentOrElement: T | RElement, keepNgReflect = false): string {
|
||||||
let element: any;
|
let element: any;
|
||||||
if (isComponentInstance(componentOrElement)) {
|
if (isComponentInstance(componentOrElement)) {
|
||||||
const context = getContext(componentOrElement);
|
const context = getContext(componentOrElement);
|
||||||
|
@ -273,13 +273,17 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
return stringifyElement(element)
|
let html = stringifyElement(element)
|
||||||
.replace(/^<div host="">(.*)<\/div>$/, '$1')
|
.replace(/^<div host="">(.*)<\/div>$/, '$1')
|
||||||
.replace(/^<div fixture="mark">(.*)<\/div>$/, '$1')
|
.replace(/^<div fixture="mark">(.*)<\/div>$/, '$1')
|
||||||
.replace(/^<div host="mark">(.*)<\/div>$/, '$1')
|
.replace(/^<div host="mark">(.*)<\/div>$/, '$1')
|
||||||
.replace(' style=""', '')
|
.replace(' style=""', '')
|
||||||
.replace(/<!--container-->/g, '')
|
.replace(/<!--container-->/g, '')
|
||||||
.replace(/<!--ng-container-->/g, '');
|
.replace(/<!--ng-container-->/g, '');
|
||||||
|
if (!keepNgReflect) {
|
||||||
|
html = html.replace(/\sng-reflect-\S*="[^"]*"/g, '');
|
||||||
|
}
|
||||||
|
return html;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -614,7 +614,6 @@ class HiddenModule {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
fixmeIvy('to investigate') &&
|
|
||||||
it('should handle false values on attributes', async(() => {
|
it('should handle false values on attributes', async(() => {
|
||||||
renderModule(FalseAttributesModule, {document: doc}).then(output => {
|
renderModule(FalseAttributesModule, {document: doc}).then(output => {
|
||||||
expect(output).toBe(
|
expect(output).toBe(
|
||||||
|
|
Loading…
Reference in New Issue