refactor(core): move server-only DomAdapter methods into ServerRenderer (#32408)
PR Close #32408
This commit is contained in:
parent
1ed3531049
commit
970b58b13f
|
@ -39,8 +39,8 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"bundle": "TODO(i): temporarily increase the payload size limit from 105779 - this is due to a closure issue related to ESM reexports that still needs to be investigated",
|
"bundle": "TODO(i): temporarily increase the payload size limit from 105779 - this is due to a closure issue related to ESM reexports that still needs to be investigated",
|
||||||
"bundle": 179825
|
"bundle": 177447
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,33 +43,17 @@ export abstract class DomAdapter {
|
||||||
abstract querySelectorAll(el: any, selector: string): any[];
|
abstract querySelectorAll(el: any, selector: string): any[];
|
||||||
abstract remove(el: any): Node;
|
abstract remove(el: any): Node;
|
||||||
abstract getAttribute(element: any, attribute: string): string|null;
|
abstract getAttribute(element: any, attribute: string): string|null;
|
||||||
|
abstract appendChild(el: any, node: any): any;
|
||||||
|
abstract createElement(tagName: any, doc?: any): HTMLElement;
|
||||||
|
abstract setAttribute(element: any, name: string, value: string): any;
|
||||||
|
abstract getElementsByTagName(element: any, name: string): HTMLElement[];
|
||||||
|
abstract createHtmlDocument(): HTMLDocument;
|
||||||
|
abstract getDefaultDocument(): Document;
|
||||||
|
|
||||||
// Used by platform-server
|
// Used by platform-server
|
||||||
abstract setProperty(el: Element, name: string, value: any): any;
|
|
||||||
abstract querySelector(el: any, selector: string): any;
|
|
||||||
abstract nextSibling(el: any): Node|null;
|
|
||||||
abstract parentElement(el: any): Node|null;
|
|
||||||
abstract clearNodes(el: any): any;
|
|
||||||
abstract appendChild(el: any, node: any): any;
|
|
||||||
abstract removeChild(el: any, node: any): any;
|
|
||||||
abstract insertBefore(parent: any, ref: any, node: any): any;
|
|
||||||
abstract setText(el: any, value: string): any;
|
|
||||||
abstract createComment(text: string): any;
|
|
||||||
abstract createElement(tagName: any, doc?: any): HTMLElement;
|
|
||||||
abstract createElementNS(ns: string, tagName: string, doc?: any): Element;
|
|
||||||
abstract createTextNode(text: string, doc?: any): Text;
|
|
||||||
abstract getElementsByTagName(element: any, name: string): HTMLElement[];
|
|
||||||
abstract addClass(element: any, className: string): any;
|
|
||||||
abstract removeClass(element: any, className: string): any;
|
|
||||||
abstract getStyle(element: any, styleName: string): any;
|
abstract getStyle(element: any, styleName: string): any;
|
||||||
abstract setStyle(element: any, styleName: string, styleValue: string): any;
|
abstract setStyle(element: any, styleName: string, styleValue: string): any;
|
||||||
abstract removeStyle(element: any, styleName: string): any;
|
abstract removeStyle(element: any, styleName: string): any;
|
||||||
abstract setAttribute(element: any, name: string, value: string): any;
|
|
||||||
abstract setAttributeNS(element: any, ns: string, name: string, value: string): any;
|
|
||||||
abstract removeAttribute(element: any, attribute: string): any;
|
|
||||||
abstract removeAttributeNS(element: any, ns: string, attribute: string): any;
|
|
||||||
abstract createHtmlDocument(): HTMLDocument;
|
|
||||||
abstract getDefaultDocument(): Document;
|
|
||||||
|
|
||||||
// Used by Title
|
// Used by Title
|
||||||
abstract getTitle(doc: Document): string;
|
abstract getTitle(doc: Document): string;
|
||||||
|
@ -80,6 +64,7 @@ export abstract class DomAdapter {
|
||||||
abstract isElementNode(node: any): boolean;
|
abstract isElementNode(node: any): boolean;
|
||||||
|
|
||||||
// Used by Testability
|
// Used by Testability
|
||||||
|
abstract parentElement(el: any): Node|null;
|
||||||
abstract isShadowRoot(node: any): boolean;
|
abstract isShadowRoot(node: any): boolean;
|
||||||
abstract getHost(el: any): any;
|
abstract getHost(el: any): any;
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
let els = fixture.debugElement.queryAll(By.css('span'));
|
let els = fixture.debugElement.queryAll(By.css('span'));
|
||||||
expect(els.length).toEqual(1);
|
expect(els.length).toEqual(1);
|
||||||
getDOM().addClass(els[0].nativeElement, 'marker');
|
els[0].nativeElement.classList.add('marker');
|
||||||
expect(fixture.nativeElement).toHaveText('hello');
|
expect(fixture.nativeElement).toHaveText('hello');
|
||||||
|
|
||||||
getComponent().numberCondition = 2;
|
getComponent().numberCondition = 2;
|
||||||
|
|
|
@ -37,7 +37,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
|
|
||||||
// We must use getDOM().querySelector instead of fixture.query here
|
// We must use getDOM().querySelector instead of fixture.query here
|
||||||
// since the elements inside are not compiled.
|
// since the elements inside are not compiled.
|
||||||
const span = getDOM().querySelector(fixture.nativeElement, '#child');
|
const span = fixture.nativeElement.querySelector('#child');
|
||||||
expect(hasClass(span, 'compiled')).toBeFalsy();
|
expect(hasClass(span, 'compiled')).toBeFalsy();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
const template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>';
|
const template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>';
|
||||||
const fixture = createTestComponent(template);
|
const fixture = createTestComponent(template);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const span = getDOM().querySelector(fixture.nativeElement, '#child');
|
const span = fixture.nativeElement.querySelector('#child');
|
||||||
expect(hasClass(span, 'compiled')).toBeTruthy();
|
expect(hasClass(span, 'compiled')).toBeTruthy();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
|
|
||||||
@Directive({selector: '[test-dec]'})
|
@Directive({selector: '[test-dec]'})
|
||||||
class TestDirective {
|
class TestDirective {
|
||||||
constructor(el: ElementRef) { getDOM().addClass(el.nativeElement, 'compiled'); }
|
constructor(el: ElementRef) { el.nativeElement.classList.add('compiled'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'test-cmp', template: ''})
|
@Component({selector: 'test-cmp', template: ''})
|
||||||
|
|
|
@ -1589,7 +1589,7 @@ const DEFAULT_COMPONENT_ID = '1';
|
||||||
engine.flush();
|
engine.flush();
|
||||||
resetLog();
|
resetLog();
|
||||||
|
|
||||||
const element = getDOM().querySelector(fixture.nativeElement, '.ng-if');
|
const element = fixture.nativeElement.querySelector('.ng-if');
|
||||||
assertHasParent(element, true);
|
assertHasParent(element, true);
|
||||||
|
|
||||||
cmp.exp = false;
|
cmp.exp = false;
|
||||||
|
|
|
@ -18,7 +18,7 @@ import {isTextNode} from '@angular/platform-browser/testing/src/browser_util';
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to create text nodes and use them with the other APIs', () => {
|
it('should be able to create text nodes and use them with the other APIs', () => {
|
||||||
const t = getDOM().createTextNode('hello');
|
const t = getDOM().getDefaultDocument().createTextNode('hello');
|
||||||
expect(isTextNode(t)).toBe(true);
|
expect(isTextNode(t)).toBe(true);
|
||||||
const d = getDOM().createElement('div');
|
const d = getDOM().createElement('div');
|
||||||
getDOM().appendChild(d, t);
|
getDOM().appendChild(d, t);
|
||||||
|
@ -71,7 +71,7 @@ import {isTextNode} from '@angular/platform-browser/testing/src/browser_util';
|
||||||
getDOM().appendChild(headEl, baseEl);
|
getDOM().appendChild(headEl, baseEl);
|
||||||
|
|
||||||
const baseHref = getDOM().getBaseHref(defaultDoc);
|
const baseHref = getDOM().getBaseHref(defaultDoc);
|
||||||
getDOM().removeChild(headEl, baseEl);
|
headEl.removeChild(baseEl);
|
||||||
getDOM().resetBaseElement();
|
getDOM().resetBaseElement();
|
||||||
|
|
||||||
expect(baseHref).toEqual('/drop/bass/connon/');
|
expect(baseHref).toEqual('/drop/bass/connon/');
|
||||||
|
@ -84,7 +84,7 @@ import {isTextNode} from '@angular/platform-browser/testing/src/browser_util';
|
||||||
getDOM().appendChild(headEl, baseEl);
|
getDOM().appendChild(headEl, baseEl);
|
||||||
|
|
||||||
const baseHref = getDOM().getBaseHref(defaultDoc) !;
|
const baseHref = getDOM().getBaseHref(defaultDoc) !;
|
||||||
getDOM().removeChild(headEl, baseEl);
|
headEl.removeChild(baseEl);
|
||||||
getDOM().resetBaseElement();
|
getDOM().resetBaseElement();
|
||||||
|
|
||||||
expect(baseHref.endsWith('/base')).toBe(true);
|
expect(baseHref.endsWith('/base')).toBe(true);
|
||||||
|
|
|
@ -1694,7 +1694,7 @@ function declareTests(config?: {useJit: boolean}) {
|
||||||
fixture.componentInstance.ctxProp = 'TITLE';
|
fixture.componentInstance.ctxProp = 'TITLE';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const el = getDOM().querySelector(fixture.nativeElement, 'span');
|
const el = fixture.nativeElement.querySelector('span');
|
||||||
expect(el.title).toBeFalsy();
|
expect(el.title).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1707,7 +1707,7 @@ function declareTests(config?: {useJit: boolean}) {
|
||||||
fixture.componentInstance.ctxProp = 'TITLE';
|
fixture.componentInstance.ctxProp = 'TITLE';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const el = getDOM().querySelector(fixture.nativeElement, 'span');
|
const el = fixture.nativeElement.querySelector('span');
|
||||||
expect(getDOM().getProperty(el, 'title')).toEqual('TITLE');
|
expect(getDOM().getProperty(el, 'title')).toEqual('TITLE');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2685,16 +2685,12 @@ class ComponentWithoutView {
|
||||||
|
|
||||||
@Directive({selector: '[no-duplicate]'})
|
@Directive({selector: '[no-duplicate]'})
|
||||||
class DuplicateDir {
|
class DuplicateDir {
|
||||||
constructor(elRef: ElementRef) {
|
constructor(elRef: ElementRef) { elRef.nativeElement.textContent += 'noduplicate'; }
|
||||||
getDOM().setText(elRef.nativeElement, elRef.nativeElement.textContent + 'noduplicate');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[no-duplicate]'})
|
@Directive({selector: '[no-duplicate]'})
|
||||||
class OtherDuplicateDir {
|
class OtherDuplicateDir {
|
||||||
constructor(elRef: ElementRef) {
|
constructor(elRef: ElementRef) { elRef.nativeElement.textContent += 'othernoduplicate'; }
|
||||||
getDOM().setText(elRef.nativeElement, elRef.nativeElement.textContent + 'othernoduplicate');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: 'directive-throwing-error'})
|
@Directive({selector: 'directive-throwing-error'})
|
||||||
|
|
|
@ -136,8 +136,9 @@ describe('projection', () => {
|
||||||
componentFactoryResolver.resolveComponentFactory(MultipleContentTagsComponent);
|
componentFactoryResolver.resolveComponentFactory(MultipleContentTagsComponent);
|
||||||
expect(componentFactory.ngContentSelectors).toEqual(['h1', '*']);
|
expect(componentFactory.ngContentSelectors).toEqual(['h1', '*']);
|
||||||
|
|
||||||
const nodeOne = getDOM().createTextNode('one');
|
|
||||||
const nodeTwo = getDOM().createTextNode('two');
|
const nodeOne = getDOM().getDefaultDocument().createTextNode('one');
|
||||||
|
const nodeTwo = getDOM().getDefaultDocument().createTextNode('two');
|
||||||
const component = componentFactory.create(injector, [[nodeOne], [nodeTwo]]);
|
const component = componentFactory.create(injector, [[nodeOne], [nodeTwo]]);
|
||||||
expect(component.location.nativeElement).toHaveText('(one, two)');
|
expect(component.location.nativeElement).toHaveText('(one, two)');
|
||||||
});
|
});
|
||||||
|
@ -175,9 +176,9 @@ describe('projection', () => {
|
||||||
componentFactoryResolver.resolveComponentFactory(MultipleContentTagsComponent);
|
componentFactoryResolver.resolveComponentFactory(MultipleContentTagsComponent);
|
||||||
expect(componentFactory.ngContentSelectors).toEqual(['h1', '*', 'h2']);
|
expect(componentFactory.ngContentSelectors).toEqual(['h1', '*', 'h2']);
|
||||||
|
|
||||||
const nodeOne = getDOM().createTextNode('one');
|
const nodeOne = getDOM().getDefaultDocument().createTextNode('one');
|
||||||
const nodeTwo = getDOM().createTextNode('two');
|
const nodeTwo = getDOM().getDefaultDocument().createTextNode('two');
|
||||||
const nodeThree = getDOM().createTextNode('three');
|
const nodeThree = getDOM().getDefaultDocument().createTextNode('three');
|
||||||
const component = componentFactory.create(injector, [[nodeOne], [nodeTwo], [nodeThree]]);
|
const component = componentFactory.create(injector, [[nodeOne], [nodeTwo], [nodeThree]]);
|
||||||
component.changeDetectorRef.detectChanges();
|
component.changeDetectorRef.detectChanges();
|
||||||
expect(component.location.nativeElement.textContent.trim()).toBe('1one 2two 3three');
|
expect(component.location.nativeElement.textContent.trim()).toBe('1one 2two 3three');
|
||||||
|
|
|
@ -74,7 +74,6 @@ const nodeContains: (this: Node, other: Node) => boolean = (() => {
|
||||||
/* tslint:disable:requireParameterType no-console */
|
/* tslint:disable:requireParameterType no-console */
|
||||||
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); }
|
static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); }
|
||||||
setProperty(el: Node, name: string, value: any) { (<any>el)[name] = value; }
|
|
||||||
getProperty(el: Node, name: string): any { return (<any>el)[name]; }
|
getProperty(el: Node, name: string): any { return (<any>el)[name]; }
|
||||||
|
|
||||||
log(error: string): void {
|
log(error: string): void {
|
||||||
|
@ -95,7 +94,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
querySelector(el: HTMLElement, selector: string): any { return el.querySelector(selector); }
|
|
||||||
querySelectorAll(el: any, selector: string): any[] { return el.querySelectorAll(selector); }
|
querySelectorAll(el: any, selector: string): any[] { return el.querySelectorAll(selector); }
|
||||||
onAndCancel(el: Node, evt: any, listener: any): Function {
|
onAndCancel(el: Node, evt: any, listener: any): Function {
|
||||||
el.addEventListener(evt, listener, false);
|
el.addEventListener(evt, listener, false);
|
||||||
|
@ -104,43 +102,23 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
return () => { el.removeEventListener(evt, listener, false); };
|
return () => { el.removeEventListener(evt, listener, false); };
|
||||||
}
|
}
|
||||||
dispatchEvent(el: Node, evt: any) { el.dispatchEvent(evt); }
|
dispatchEvent(el: Node, evt: any) { el.dispatchEvent(evt); }
|
||||||
nextSibling(el: Node): Node|null { return el.nextSibling; }
|
|
||||||
parentElement(el: Node): Node|null { return el.parentNode; }
|
parentElement(el: Node): Node|null { return el.parentNode; }
|
||||||
clearNodes(el: Node) {
|
|
||||||
while (el.firstChild) {
|
|
||||||
el.removeChild(el.firstChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendChild(el: Node, node: Node) { el.appendChild(node); }
|
appendChild(el: Node, node: Node) { el.appendChild(node); }
|
||||||
removeChild(el: Node, node: Node) { el.removeChild(node); }
|
|
||||||
remove(node: Node): Node {
|
remove(node: Node): Node {
|
||||||
if (node.parentNode) {
|
if (node.parentNode) {
|
||||||
node.parentNode.removeChild(node);
|
node.parentNode.removeChild(node);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
insertBefore(parent: Node, ref: Node, node: Node) { parent.insertBefore(node, ref); }
|
|
||||||
setText(el: Node, value: string) { el.textContent = value; }
|
|
||||||
getValue(el: any): string { return el.value; }
|
getValue(el: any): string { return el.value; }
|
||||||
createComment(text: string): Comment { return this.getDefaultDocument().createComment(text); }
|
|
||||||
createElement(tagName: string, doc?: Document): HTMLElement {
|
createElement(tagName: string, doc?: Document): HTMLElement {
|
||||||
doc = doc || this.getDefaultDocument();
|
doc = doc || this.getDefaultDocument();
|
||||||
return doc.createElement(tagName);
|
return doc.createElement(tagName);
|
||||||
}
|
}
|
||||||
createElementNS(ns: string, tagName: string, doc?: Document): Element {
|
|
||||||
doc = doc || this.getDefaultDocument();
|
|
||||||
return doc.createElementNS(ns, tagName);
|
|
||||||
}
|
|
||||||
createTextNode(text: string, doc?: Document): Text {
|
|
||||||
doc = doc || this.getDefaultDocument();
|
|
||||||
return doc.createTextNode(text);
|
|
||||||
}
|
|
||||||
getHost(el: HTMLElement): HTMLElement { return (<any>el).host; }
|
getHost(el: HTMLElement): HTMLElement { return (<any>el).host; }
|
||||||
getElementsByTagName(element: any, name: string): HTMLElement[] {
|
getElementsByTagName(element: any, name: string): HTMLElement[] {
|
||||||
return element.getElementsByTagName(name);
|
return element.getElementsByTagName(name);
|
||||||
}
|
}
|
||||||
addClass(element: any, className: string) { element.classList.add(className); }
|
|
||||||
removeClass(element: any, className: string) { element.classList.remove(className); }
|
|
||||||
setStyle(element: any, styleName: string, styleValue: string) {
|
setStyle(element: any, styleName: string, styleValue: string) {
|
||||||
element.style[styleName] = styleValue;
|
element.style[styleName] = styleValue;
|
||||||
}
|
}
|
||||||
|
@ -156,13 +134,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||||
return element.getAttribute(attribute);
|
return element.getAttribute(attribute);
|
||||||
}
|
}
|
||||||
setAttribute(element: Element, name: string, value: string) { element.setAttribute(name, value); }
|
setAttribute(element: Element, name: string, value: string) { element.setAttribute(name, value); }
|
||||||
setAttributeNS(element: Element, ns: string, name: string, value: string) {
|
|
||||||
element.setAttributeNS(ns, name, value);
|
|
||||||
}
|
|
||||||
removeAttribute(element: Element, attribute: string) { element.removeAttribute(attribute); }
|
|
||||||
removeAttributeNS(element: Element, ns: string, name: string) {
|
|
||||||
element.removeAttributeNS(ns, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
createHtmlDocument(): HTMLDocument {
|
createHtmlDocument(): HTMLDocument {
|
||||||
return document.implementation.createHTMLDocument('fakeTitle');
|
return document.implementation.createHTMLDocument('fakeTitle');
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class Meta {
|
||||||
|
|
||||||
getTag(attrSelector: string): HTMLMetaElement|null {
|
getTag(attrSelector: string): HTMLMetaElement|null {
|
||||||
if (!attrSelector) return null;
|
if (!attrSelector) return null;
|
||||||
return this._dom.querySelector(this._doc, `meta[${attrSelector}]`) || null;
|
return this._doc.querySelector(`meta[${attrSelector}]`) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTags(attrSelector: string): HTMLMetaElement[] {
|
getTags(attrSelector: string): HTMLMetaElement[] {
|
||||||
|
|
|
@ -153,7 +153,7 @@ function bootstrap(
|
||||||
getDOM().appendChild(doc.body, el);
|
getDOM().appendChild(doc.body, el);
|
||||||
getDOM().appendChild(doc.body, el2);
|
getDOM().appendChild(doc.body, el2);
|
||||||
getDOM().appendChild(el, lightDom);
|
getDOM().appendChild(el, lightDom);
|
||||||
getDOM().setText(lightDom, 'loading');
|
lightDom.textContent = 'loading';
|
||||||
}));
|
}));
|
||||||
|
|
||||||
afterEach(destroyPlatform);
|
afterEach(destroyPlatform);
|
||||||
|
|
|
@ -86,18 +86,6 @@ export class DominoAdapter extends BrowserDomAdapter {
|
||||||
return (<any>el)[name];
|
return (<any>el)[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperty(el: Element, name: string, value: any) {
|
|
||||||
if (name === 'href') {
|
|
||||||
// Even though the server renderer reflects any properties to attributes
|
|
||||||
// map 'href' to attribute just to handle when setProperty is directly called.
|
|
||||||
this.setAttribute(el, 'href', value);
|
|
||||||
} else if (name === 'innerText') {
|
|
||||||
// Domino does not support innerText. Just map it to textContent.
|
|
||||||
el.textContent = value;
|
|
||||||
}
|
|
||||||
(<any>el)[name] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGlobalEventTarget(doc: Document, target: string): EventTarget|null {
|
getGlobalEventTarget(doc: Document, target: string): EventTarget|null {
|
||||||
if (target === 'window') {
|
if (target === 'window') {
|
||||||
return doc.defaultView;
|
return doc.defaultView;
|
||||||
|
@ -112,7 +100,7 @@ export class DominoAdapter extends BrowserDomAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
getBaseHref(doc: Document): string {
|
getBaseHref(doc: Document): string {
|
||||||
const base = this.querySelector(doc.documentElement !, 'base');
|
const base = doc.documentElement !.querySelector('base');
|
||||||
let href = '';
|
let href = '';
|
||||||
if (base) {
|
if (base) {
|
||||||
href = base.getAttribute('href') !;
|
href = base.getAttribute('href') !;
|
||||||
|
|
|
@ -72,51 +72,59 @@ class DefaultServerRenderer2 implements Renderer2 {
|
||||||
|
|
||||||
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
createElement(name: string, namespace?: string, debugInfo?: any): any {
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
return getDOM().createElementNS(NAMESPACE_URIS[namespace], name, this.document);
|
const doc = this.document || getDOM().getDefaultDocument();
|
||||||
|
return doc.createElementNS(NAMESPACE_URIS[namespace], name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDOM().createElement(name, this.document);
|
return getDOM().createElement(name, this.document);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComment(value: string, debugInfo?: any): any { return getDOM().createComment(value); }
|
createComment(value: string, debugInfo?: any): any {
|
||||||
|
return getDOM().getDefaultDocument().createComment(value);
|
||||||
|
}
|
||||||
|
|
||||||
createText(value: string, debugInfo?: any): any { return getDOM().createTextNode(value); }
|
createText(value: string, debugInfo?: any): any {
|
||||||
|
const doc = getDOM().getDefaultDocument();
|
||||||
|
return doc.createTextNode(value);
|
||||||
|
}
|
||||||
|
|
||||||
appendChild(parent: any, newChild: any): void { getDOM().appendChild(parent, newChild); }
|
appendChild(parent: any, newChild: any): void { getDOM().appendChild(parent, newChild); }
|
||||||
|
|
||||||
insertBefore(parent: any, newChild: any, refChild: any): void {
|
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||||||
if (parent) {
|
if (parent) {
|
||||||
getDOM().insertBefore(parent, refChild, newChild);
|
parent.insertBefore(newChild, refChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeChild(parent: any, oldChild: any): void {
|
removeChild(parent: any, oldChild: any): void {
|
||||||
if (parent) {
|
if (parent) {
|
||||||
getDOM().removeChild(parent, oldChild);
|
parent.removeChild(oldChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectRootElement(selectorOrNode: string|any, debugInfo?: any): any {
|
selectRootElement(selectorOrNode: string|any, debugInfo?: any): any {
|
||||||
let el: any;
|
let el: any;
|
||||||
if (typeof selectorOrNode === 'string') {
|
if (typeof selectorOrNode === 'string') {
|
||||||
el = getDOM().querySelector(this.document, selectorOrNode);
|
el = this.document.querySelector(selectorOrNode);
|
||||||
if (!el) {
|
if (!el) {
|
||||||
throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
|
throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
el = selectorOrNode;
|
el = selectorOrNode;
|
||||||
}
|
}
|
||||||
getDOM().clearNodes(el);
|
while (el.firstChild) {
|
||||||
|
el.removeChild(el.firstChild);
|
||||||
|
}
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
parentNode(node: any): any { return getDOM().parentElement(node); }
|
parentNode(node: any): any { return getDOM().parentElement(node); }
|
||||||
|
|
||||||
nextSibling(node: any): any { return getDOM().nextSibling(node); }
|
nextSibling(node: any): any { return node.nextSibling; }
|
||||||
|
|
||||||
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
getDOM().setAttributeNS(el, NAMESPACE_URIS[namespace], namespace + ':' + name, value);
|
el.setAttributeNS(NAMESPACE_URIS[namespace], namespace + ':' + name, value);
|
||||||
} else {
|
} else {
|
||||||
getDOM().setAttribute(el, name, value);
|
getDOM().setAttribute(el, name, value);
|
||||||
}
|
}
|
||||||
|
@ -124,15 +132,15 @@ class DefaultServerRenderer2 implements Renderer2 {
|
||||||
|
|
||||||
removeAttribute(el: any, name: string, namespace?: string): void {
|
removeAttribute(el: any, name: string, namespace?: string): void {
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
getDOM().removeAttributeNS(el, NAMESPACE_URIS[namespace], name);
|
el.removeAttributeNS(NAMESPACE_URIS[namespace], name);
|
||||||
} else {
|
} else {
|
||||||
getDOM().removeAttribute(el, name);
|
el.removeAttribute(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addClass(el: any, name: string): void { getDOM().addClass(el, name); }
|
addClass(el: any, name: string): void { el.classList.add(name); }
|
||||||
|
|
||||||
removeClass(el: any, name: string): void { getDOM().removeClass(el, name); }
|
removeClass(el: any, name: string): void { el.classList.remove(name); }
|
||||||
|
|
||||||
setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {
|
setStyle(el: any, style: string, value: any, flags: RendererStyleFlags2): void {
|
||||||
getDOM().setStyle(el, style, value);
|
getDOM().setStyle(el, style, value);
|
||||||
|
@ -153,7 +161,11 @@ class DefaultServerRenderer2 implements Renderer2 {
|
||||||
|
|
||||||
setProperty(el: any, name: string, value: any): void {
|
setProperty(el: any, name: string, value: any): void {
|
||||||
checkNoSyntheticProp(name, 'property');
|
checkNoSyntheticProp(name, 'property');
|
||||||
getDOM().setProperty(el, name, value);
|
if (name === 'innerText') {
|
||||||
|
// Domino does not support innerText. Just map it to textContent.
|
||||||
|
el.textContent = value;
|
||||||
|
}
|
||||||
|
(<any>el)[name] = value;
|
||||||
// Mirror property values for known HTML element properties in the attributes.
|
// Mirror property values for known HTML element properties in the attributes.
|
||||||
// Skip `innerhtml` which is conservatively marked as an attribute for security
|
// Skip `innerhtml` which is conservatively marked as an attribute for security
|
||||||
// purposes but is not actually an attribute.
|
// purposes but is not actually an attribute.
|
||||||
|
@ -166,7 +178,7 @@ class DefaultServerRenderer2 implements Renderer2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(node: any, value: string): void { getDOM().setText(node, value); }
|
setValue(node: any, value: string): void { node.textContent = value; }
|
||||||
|
|
||||||
listen(
|
listen(
|
||||||
target: 'document'|'window'|'body'|any, eventName: string,
|
target: 'document'|'window'|'body'|any, eventName: string,
|
||||||
|
|
|
@ -24,7 +24,7 @@ export class ServerStylesHost extends SharedStylesHost {
|
||||||
private _addStyle(style: string): void {
|
private _addStyle(style: string): void {
|
||||||
let adapter = getDOM();
|
let adapter = getDOM();
|
||||||
const el = adapter.createElement('style');
|
const el = adapter.createElement('style');
|
||||||
adapter.setText(el, style);
|
el.textContent = style;
|
||||||
if (!!this.transitionId) {
|
if (!!this.transitionId) {
|
||||||
adapter.setAttribute(el, 'ng-transition', this.transitionId);
|
adapter.setAttribute(el, 'ng-transition', this.transitionId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,8 +408,8 @@ class HiddenModule {
|
||||||
expect(isPlatformServer(moduleRef.injector.get(PLATFORM_ID))).toBe(true);
|
expect(isPlatformServer(moduleRef.injector.get(PLATFORM_ID))).toBe(true);
|
||||||
const doc = moduleRef.injector.get(DOCUMENT);
|
const doc = moduleRef.injector.get(DOCUMENT);
|
||||||
|
|
||||||
expect(doc.head).toBe(getDOM().querySelector(doc, 'head'));
|
expect(doc.head).toBe(doc.querySelector('head') !);
|
||||||
expect(doc.body).toBe(getDOM().querySelector(doc, 'body'));
|
expect(doc.body).toBe(doc.querySelector('body') !);
|
||||||
|
|
||||||
expect(doc.documentElement.textContent).toEqual('Works!');
|
expect(doc.documentElement.textContent).toEqual('Works!');
|
||||||
|
|
||||||
|
@ -447,7 +447,7 @@ class HiddenModule {
|
||||||
platform.bootstrapModule(TitleAppModule).then(ref => {
|
platform.bootstrapModule(TitleAppModule).then(ref => {
|
||||||
const state = ref.injector.get(PlatformState);
|
const state = ref.injector.get(PlatformState);
|
||||||
const doc = ref.injector.get(DOCUMENT);
|
const doc = ref.injector.get(DOCUMENT);
|
||||||
const title = getDOM().querySelector(doc, 'title');
|
const title = doc.querySelector('title') !;
|
||||||
expect(title.textContent).toBe('Test App Title');
|
expect(title.textContent).toBe('Test App Title');
|
||||||
expect(state.renderToString()).toContain('<title>Test App Title</title>');
|
expect(state.renderToString()).toContain('<title>Test App Title</title>');
|
||||||
});
|
});
|
||||||
|
|
|
@ -42,37 +42,22 @@ export class WorkerDomAdapter extends DomAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperty(el: Element, name: string, value: any) { throw 'not implemented'; }
|
|
||||||
getProperty(el: Element, name: string): any { throw 'not implemented'; }
|
getProperty(el: Element, name: string): any { throw 'not implemented'; }
|
||||||
|
|
||||||
querySelector(el: any, selector: string): HTMLElement { throw 'not implemented'; }
|
|
||||||
querySelectorAll(el: any, selector: string): any[] { throw 'not implemented'; }
|
querySelectorAll(el: any, selector: string): any[] { throw 'not implemented'; }
|
||||||
onAndCancel(el: any, evt: any, listener: any): Function { throw 'not implemented'; }
|
onAndCancel(el: any, evt: any, listener: any): Function { throw 'not implemented'; }
|
||||||
dispatchEvent(el: any, evt: any) { throw 'not implemented'; }
|
dispatchEvent(el: any, evt: any) { throw 'not implemented'; }
|
||||||
nextSibling(el: any): Node { throw 'not implemented'; }
|
|
||||||
parentElement(el: any): Node { throw 'not implemented'; }
|
parentElement(el: any): Node { throw 'not implemented'; }
|
||||||
clearNodes(el: any) { throw 'not implemented'; }
|
|
||||||
appendChild(el: any, node: any) { throw 'not implemented'; }
|
appendChild(el: any, node: any) { throw 'not implemented'; }
|
||||||
removeChild(el: any, node: any) { throw 'not implemented'; }
|
|
||||||
remove(el: any): Node { throw 'not implemented'; }
|
remove(el: any): Node { throw 'not implemented'; }
|
||||||
insertBefore(parent: any, el: any, node: any) { throw 'not implemented'; }
|
|
||||||
setText(el: any, value: string) { throw 'not implemented'; }
|
|
||||||
createComment(text: string): any { throw 'not implemented'; }
|
|
||||||
createElement(tagName: any, doc?: any): HTMLElement { throw 'not implemented'; }
|
createElement(tagName: any, doc?: any): HTMLElement { throw 'not implemented'; }
|
||||||
createElementNS(ns: string, tagName: string, doc?: any): Element { throw 'not implemented'; }
|
|
||||||
createTextNode(text: string, doc?: any): Text { throw 'not implemented'; }
|
|
||||||
getHost(el: any): any { throw 'not implemented'; }
|
getHost(el: any): any { throw 'not implemented'; }
|
||||||
getElementsByTagName(element: any, name: string): HTMLElement[] { throw 'not implemented'; }
|
getElementsByTagName(element: any, name: string): HTMLElement[] { throw 'not implemented'; }
|
||||||
addClass(element: any, className: string) { throw 'not implemented'; }
|
|
||||||
removeClass(element: any, className: string) { throw 'not implemented'; }
|
|
||||||
setStyle(element: any, styleName: string, styleValue: string) { throw 'not implemented'; }
|
setStyle(element: any, styleName: string, styleValue: string) { throw 'not implemented'; }
|
||||||
removeStyle(element: any, styleName: string) { throw 'not implemented'; }
|
removeStyle(element: any, styleName: string) { throw 'not implemented'; }
|
||||||
getStyle(element: any, styleName: string): string { throw 'not implemented'; }
|
getStyle(element: any, styleName: string): string { throw 'not implemented'; }
|
||||||
getAttribute(element: any, attribute: string): string { throw 'not implemented'; }
|
getAttribute(element: any, attribute: string): string { throw 'not implemented'; }
|
||||||
setAttribute(element: any, name: string, value: string) { throw 'not implemented'; }
|
setAttribute(element: any, name: string, value: string) { throw 'not implemented'; }
|
||||||
setAttributeNS(element: any, ns: string, name: string, value: string) { throw 'not implemented'; }
|
|
||||||
removeAttribute(element: any, attribute: string) { throw 'not implemented'; }
|
|
||||||
removeAttributeNS(element: any, ns: string, attribute: string) { throw 'not implemented'; }
|
|
||||||
createHtmlDocument(): HTMLDocument { throw 'not implemented'; }
|
createHtmlDocument(): HTMLDocument { throw 'not implemented'; }
|
||||||
getDefaultDocument(): Document { throw 'not implemented'; }
|
getDefaultDocument(): Document { throw 'not implemented'; }
|
||||||
getTitle(doc: Document): string { throw 'not implemented'; }
|
getTitle(doc: Document): string { throw 'not implemented'; }
|
||||||
|
|
Loading…
Reference in New Issue