@angular/platform-server
Version:
Angular - library for using Angular in Node.js
1,470 lines (1,451 loc) • 43.7 kB
JavaScript
/**
* @license Angular v5.0.0-rc.8
* (c) 2010-2017 Google, Inc. https://angular.io/
* License: MIT
*/
import { APP_ID, ApplicationRef, Inject, Injectable, InjectionToken, Injector, NgModule, NgZone, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, RendererFactory2, Testability, Version, ViewEncapsulation, createPlatformFactory, platformCore, ɵALLOW_MULTIPLE_PLATFORMS } from '@angular/core';
import { BrowserModule, DOCUMENT, TransferState, ɵBrowserDomAdapter, ɵNAMESPACE_URIS, ɵSharedStylesHost, ɵTRANSITION_ID, ɵescapeHtml, ɵflattenStyles, ɵgetDOM, ɵsetRootDomAdapter, ɵshimContentAttribute, ɵshimHostAttribute } from '@angular/platform-browser';
import { ɵAnimationEngine } from '@angular/animations/browser';
import { PlatformLocation, ɵPLATFORM_SERVER_ID } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpBackend, HttpClientModule, HttpHandler, XhrFactory, ɵinterceptingHandler } from '@angular/common/http';
import { BrowserXhr, Http, HttpModule, ReadyState, RequestOptions, XHRBackend, XSRFStrategy } from '@angular/http';
import { ɵplatformCoreDynamic } from '@angular/platform-browser-dynamic';
import { NoopAnimationsModule, ɵAnimationRendererFactory } from '@angular/platform-browser/animations';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { parse } from 'url';
import { DomElementSchemaRegistry } from '@angular/compiler';
import { filter } from 'rxjs/operator/filter';
import { first } from 'rxjs/operator/first';
import { toPromise } from 'rxjs/operator/toPromise';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
const domino = require('domino');
/**
* @param {?} methodName
* @return {?}
*/
function _notImplemented(methodName) {
return new Error('This method is not implemented in DominoAdapter: ' + methodName);
}
/**
* Parses a document string to a Document object.
* @param {?} html
* @param {?=} url
* @return {?}
*/
function parseDocument(html, url$$1 = '/') {
let /** @type {?} */ window = domino.createWindow(html, url$$1);
let /** @type {?} */ doc = window.document;
return doc;
}
/**
* Serializes a document to string.
* @param {?} doc
* @return {?}
*/
function serializeDocument(doc) {
return (/** @type {?} */ (doc)).serialize();
}
/**
* DOM Adapter for the server platform based on https://github.com/fgnass/domino.
*/
class DominoAdapter extends ɵBrowserDomAdapter {
/**
* @return {?}
*/
static makeCurrent() { ɵsetRootDomAdapter(new DominoAdapter()); }
/**
* @param {?} error
* @return {?}
*/
logError(error) { console.error(error); }
/**
* @param {?} error
* @return {?}
*/
log(error) {
// tslint:disable-next-line:no-console
console.log(error);
}
/**
* @param {?} error
* @return {?}
*/
logGroup(error) { console.error(error); }
/**
* @return {?}
*/
logGroupEnd() { }
/**
* @return {?}
*/
supportsDOMEvents() { return false; }
/**
* @return {?}
*/
supportsNativeShadowDOM() { return false; }
/**
* @param {?} nodeA
* @param {?} nodeB
* @return {?}
*/
contains(nodeA, nodeB) {
let /** @type {?} */ inner = nodeB;
while (inner) {
if (inner === nodeA)
return true;
inner = inner.parent;
}
return false;
}
/**
* @return {?}
*/
createHtmlDocument() {
return parseDocument('<html><head><title>fakeTitle</title></head><body></body></html>');
}
/**
* @return {?}
*/
getDefaultDocument() {
if (!DominoAdapter.defaultDoc) {
DominoAdapter.defaultDoc = domino.createDocument();
}
return DominoAdapter.defaultDoc;
}
/**
* @param {?} el
* @param {?=} doc
* @return {?}
*/
createShadowRoot(el, doc = document) {
el.shadowRoot = doc.createDocumentFragment();
el.shadowRoot.parent = el;
return el.shadowRoot;
}
/**
* @param {?} el
* @return {?}
*/
getShadowRoot(el) { return el.shadowRoot; }
/**
* @param {?} node
* @return {?}
*/
isTextNode(node) { return node.nodeType === DominoAdapter.defaultDoc.TEXT_NODE; }
/**
* @param {?} node
* @return {?}
*/
isCommentNode(node) {
return node.nodeType === DominoAdapter.defaultDoc.COMMENT_NODE;
}
/**
* @param {?} node
* @return {?}
*/
isElementNode(node) {
return node ? node.nodeType === DominoAdapter.defaultDoc.ELEMENT_NODE : false;
}
/**
* @param {?} node
* @return {?}
*/
hasShadowRoot(node) { return node.shadowRoot != null; }
/**
* @param {?} node
* @return {?}
*/
isShadowRoot(node) { return this.getShadowRoot(node) == node; }
/**
* @param {?} el
* @param {?} name
* @return {?}
*/
getProperty(el, name) {
if (name === 'href') {
// Domino tries tp resolve href-s which we do not want. Just return the
// atribute value.
return this.getAttribute(el, 'href');
}
else if (name === 'innerText') {
// Domino does not support innerText. Just map it to textContent.
return el.textContent;
}
return (/** @type {?} */ (el))[name];
}
/**
* @param {?} el
* @param {?} name
* @param {?} value
* @return {?}
*/
setProperty(el, name, value) {
if (name === 'href') {
// Eventhough the server renderer reflects any properties to attributes
// map 'href' to atribute 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;
}
(/** @type {?} */ (el))[name] = value;
}
/**
* @param {?} doc
* @param {?} target
* @return {?}
*/
getGlobalEventTarget(doc, target) {
if (target === 'window') {
return doc.defaultView;
}
if (target === 'document') {
return doc;
}
if (target === 'body') {
return doc.body;
}
return null;
}
/**
* @param {?} doc
* @return {?}
*/
getBaseHref(doc) {
const /** @type {?} */ base = this.querySelector(doc.documentElement, 'base');
let /** @type {?} */ href = '';
if (base) {
href = this.getHref(base);
}
// TODO(alxhub): Need relative path logic from BrowserDomAdapter here?
return href;
}
/**
* \@internal
* @param {?} element
* @return {?}
*/
_readStyleAttribute(element) {
const /** @type {?} */ styleMap = {};
const /** @type {?} */ styleAttribute = element.getAttribute('style');
if (styleAttribute) {
const /** @type {?} */ styleList = styleAttribute.split(/;+/g);
for (let /** @type {?} */ i = 0; i < styleList.length; i++) {
if (styleList[i].length > 0) {
const /** @type {?} */ style = /** @type {?} */ (styleList[i]);
const /** @type {?} */ colon = style.indexOf(':');
if (colon === -1) {
throw new Error(`Invalid CSS style: ${style}`);
}
(/** @type {?} */ (styleMap))[style.substr(0, colon).trim()] = style.substr(colon + 1).trim();
}
}
}
return styleMap;
}
/**
* \@internal
* @param {?} element
* @param {?} styleMap
* @return {?}
*/
_writeStyleAttribute(element, styleMap) {
let /** @type {?} */ styleAttrValue = '';
for (const /** @type {?} */ key in styleMap) {
const /** @type {?} */ newValue = styleMap[key];
if (newValue) {
styleAttrValue += key + ':' + styleMap[key] + ';';
}
}
element.setAttribute('style', styleAttrValue);
}
/**
* @param {?} element
* @param {?} styleName
* @param {?=} styleValue
* @return {?}
*/
setStyle(element, styleName, styleValue) {
const /** @type {?} */ styleMap = this._readStyleAttribute(element);
(/** @type {?} */ (styleMap))[styleName] = styleValue;
this._writeStyleAttribute(element, styleMap);
}
/**
* @param {?} element
* @param {?} styleName
* @return {?}
*/
removeStyle(element, styleName) { this.setStyle(element, styleName, null); }
/**
* @param {?} element
* @param {?} styleName
* @return {?}
*/
getStyle(element, styleName) {
const /** @type {?} */ styleMap = this._readStyleAttribute(element);
return styleMap.hasOwnProperty(styleName) ? (/** @type {?} */ (styleMap))[styleName] : '';
}
/**
* @param {?} element
* @param {?} styleName
* @param {?=} styleValue
* @return {?}
*/
hasStyle(element, styleName, styleValue) {
const /** @type {?} */ value = this.getStyle(element, styleName) || '';
return styleValue ? value == styleValue : value.length > 0;
}
/**
* @param {?} el
* @param {?} evt
* @return {?}
*/
dispatchEvent(el, evt) {
el.dispatchEvent(evt);
// Dispatch the event to the window also.
const /** @type {?} */ doc = el.ownerDocument || el;
const /** @type {?} */ win = (/** @type {?} */ (doc)).defaultView;
if (win) {
win.dispatchEvent(evt);
}
}
/**
* @return {?}
*/
getHistory() { throw _notImplemented('getHistory'); }
/**
* @return {?}
*/
getLocation() { throw _notImplemented('getLocation'); }
/**
* @return {?}
*/
getUserAgent() { return 'Fake user agent'; }
/**
* @return {?}
*/
supportsWebAnimation() { return false; }
/**
* @return {?}
*/
performanceNow() { return Date.now(); }
/**
* @return {?}
*/
getAnimationPrefix() { return ''; }
/**
* @return {?}
*/
getTransitionEnd() { return 'transitionend'; }
/**
* @return {?}
*/
supportsAnimation() { return true; }
/**
* @param {?} el
* @return {?}
*/
getDistributedNodes(el) { throw _notImplemented('getDistributedNodes'); }
/**
* @return {?}
*/
supportsCookies() { return false; }
/**
* @param {?} name
* @return {?}
*/
getCookie(name) { throw _notImplemented('getCookie'); }
/**
* @param {?} name
* @param {?} value
* @return {?}
*/
setCookie(name, value) { throw _notImplemented('setCookie'); }
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* Representation of the current platform state.
*
* \@experimental
*/
class PlatformState {
/**
* @param {?} _doc
*/
constructor(_doc) {
this._doc = _doc;
}
/**
* Renders the current state of the platform to string.
* @return {?}
*/
renderToString() { return serializeDocument(this._doc); }
/**
* Returns the current DOM state.
* @return {?}
*/
getDocument() { return this._doc; }
}
PlatformState.decorators = [
{ type: Injectable },
];
/** @nocollapse */
PlatformState.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] },] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
const xhr2 = require('xhr2');
const isAbsoluteUrl = /^[a-zA-Z\-\+.]+:\/\//;
/**
* @param {?} url
* @return {?}
*/
function validateRequestUrl(url$$1) {
if (!isAbsoluteUrl.test(url$$1)) {
throw new Error(`URLs requested via Http on the server must be absolute. URL: ${url$$1}`);
}
}
class ServerXhr {
/**
* @return {?}
*/
build() { return new xhr2.XMLHttpRequest(); }
}
ServerXhr.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ServerXhr.ctorParameters = () => [];
class ServerXsrfStrategy {
/**
* @param {?} req
* @return {?}
*/
configureRequest(req) { }
}
ServerXsrfStrategy.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ServerXsrfStrategy.ctorParameters = () => [];
/**
* @abstract
*/
class ZoneMacroTaskWrapper {
/**
* @param {?} request
* @return {?}
*/
wrap(request) {
return new Observable((observer) => {
let /** @type {?} */ task = /** @type {?} */ ((null));
let /** @type {?} */ scheduled = false;
let /** @type {?} */ sub = null;
let /** @type {?} */ savedResult = null;
let /** @type {?} */ savedError = null;
const /** @type {?} */ scheduleTask = (_task) => {
task = _task;
scheduled = true;
const /** @type {?} */ delegate = this.delegate(request);
sub = delegate.subscribe(res => savedResult = res, err => {
if (!scheduled) {
throw new Error('An http observable was completed twice. This shouldn\'t happen, please file a bug.');
}
savedError = err;
scheduled = false;
task.invoke();
}, () => {
if (!scheduled) {
throw new Error('An http observable was completed twice. This shouldn\'t happen, please file a bug.');
}
scheduled = false;
task.invoke();
});
};
const /** @type {?} */ cancelTask = (_task) => {
if (!scheduled) {
return;
}
scheduled = false;
if (sub) {
sub.unsubscribe();
sub = null;
}
};
const /** @type {?} */ onComplete = () => {
if (savedError !== null) {
observer.error(savedError);
}
else {
observer.next(savedResult);
observer.complete();
}
};
// MockBackend for Http is synchronous, which means that if scheduleTask is by
// scheduleMacroTask, the request will hit MockBackend and the response will be
// sent, causing task.invoke() to be called.
const /** @type {?} */ _task = Zone.current.scheduleMacroTask('ZoneMacroTaskWrapper.subscribe', onComplete, {}, () => null, cancelTask);
scheduleTask(_task);
return () => {
if (scheduled && task) {
task.zone.cancelTask(task);
scheduled = false;
}
if (sub) {
sub.unsubscribe();
sub = null;
}
};
});
}
}
class ZoneMacroTaskConnection extends ZoneMacroTaskWrapper {
/**
* @param {?} request
* @param {?} backend
*/
constructor(request, backend) {
super();
this.request = request;
this.backend = backend;
validateRequestUrl(request.url);
this.response = this.wrap(request);
}
/**
* @param {?} request
* @return {?}
*/
delegate(request) {
this.lastConnection = this.backend.createConnection(request);
return /** @type {?} */ (this.lastConnection.response);
}
/**
* @return {?}
*/
get readyState() {
return !!this.lastConnection ? this.lastConnection.readyState : ReadyState.Unsent;
}
}
class ZoneMacroTaskBackend {
/**
* @param {?} backend
*/
constructor(backend) {
this.backend = backend;
}
/**
* @param {?} request
* @return {?}
*/
createConnection(request) {
return new ZoneMacroTaskConnection(request, this.backend);
}
}
class ZoneClientBackend extends ZoneMacroTaskWrapper {
/**
* @param {?} backend
*/
constructor(backend) {
super();
this.backend = backend;
}
/**
* @param {?} request
* @return {?}
*/
handle(request) { return this.wrap(request); }
/**
* @param {?} request
* @return {?}
*/
delegate(request) {
return this.backend.handle(request);
}
}
/**
* @param {?} xhrBackend
* @param {?} options
* @return {?}
*/
function httpFactory(xhrBackend, options) {
const /** @type {?} */ macroBackend = new ZoneMacroTaskBackend(xhrBackend);
return new Http(macroBackend, options);
}
/**
* @param {?} backend
* @param {?} interceptors
* @return {?}
*/
function zoneWrappedInterceptingHandler(backend, interceptors) {
const /** @type {?} */ realBackend = ɵinterceptingHandler(backend, interceptors);
return new ZoneClientBackend(realBackend);
}
const SERVER_HTTP_PROVIDERS = [
{ provide: Http, useFactory: httpFactory, deps: [XHRBackend, RequestOptions] },
{ provide: BrowserXhr, useClass: ServerXhr }, { provide: XSRFStrategy, useClass: ServerXsrfStrategy },
{ provide: XhrFactory, useClass: ServerXhr }, {
provide: HttpHandler,
useFactory: zoneWrappedInterceptingHandler,
deps: [HttpBackend, [new Optional(), HTTP_INTERCEPTORS]]
}
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* Config object passed to initialize the platform.
*
* \@experimental
* @record
*/
/**
* The DI token for setting the initial config for the platform.
*
* \@experimental
*/
const INITIAL_CONFIG = new InjectionToken('Server.INITIAL_CONFIG');
/**
* A function that will be executed when calling `renderModuleFactory` or `renderModule` just
* before current platform state is rendered to string.
*
* \@experimental
*/
const BEFORE_APP_SERIALIZED = new InjectionToken('Server.RENDER_MODULE_HOOK');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @param {?} urlStr
* @return {?}
*/
function parseUrl(urlStr) {
const /** @type {?} */ parsedUrl = parse(urlStr);
return {
pathname: parsedUrl.pathname || '',
search: parsedUrl.search || '',
hash: parsedUrl.hash || '',
};
}
/**
* Server-side implementation of URL state. Implements `pathname`, `search`, and `hash`
* but not the state stack.
*/
class ServerPlatformLocation {
/**
* @param {?} _doc
* @param {?} _config
*/
constructor(_doc, _config) {
this._doc = _doc;
this.pathname = '/';
this.search = '';
this.hash = '';
this._hashUpdate = new Subject();
const /** @type {?} */ config = /** @type {?} */ (_config);
if (!!config && !!config.url) {
const /** @type {?} */ parsedUrl = parseUrl(config.url);
this.pathname = parsedUrl.pathname;
this.search = parsedUrl.search;
this.hash = parsedUrl.hash;
}
}
/**
* @return {?}
*/
getBaseHrefFromDOM() { return /** @type {?} */ ((ɵgetDOM().getBaseHref(this._doc))); }
/**
* @param {?} fn
* @return {?}
*/
onPopState(fn) {
// No-op: a state stack is not implemented, so
// no events will ever come.
}
/**
* @param {?} fn
* @return {?}
*/
onHashChange(fn) { this._hashUpdate.subscribe(fn); }
/**
* @return {?}
*/
get url() { return `${this.pathname}${this.search}${this.hash}`; }
/**
* @param {?} value
* @param {?} oldUrl
* @return {?}
*/
setHash(value, oldUrl) {
if (this.hash === value) {
// Don't fire events if the hash has not changed.
return;
}
(/** @type {?} */ (this)).hash = value;
const /** @type {?} */ newUrl = this.url;
scheduleMicroTask(() => this._hashUpdate.next(/** @type {?} */ ({ type: 'hashchange', oldUrl, newUrl })));
}
/**
* @param {?} state
* @param {?} title
* @param {?} newUrl
* @return {?}
*/
replaceState(state, title, newUrl) {
const /** @type {?} */ oldUrl = this.url;
const /** @type {?} */ parsedUrl = parseUrl(newUrl);
(/** @type {?} */ (this)).pathname = parsedUrl.pathname;
(/** @type {?} */ (this)).search = parsedUrl.search;
this.setHash(parsedUrl.hash, oldUrl);
}
/**
* @param {?} state
* @param {?} title
* @param {?} newUrl
* @return {?}
*/
pushState(state, title, newUrl) {
this.replaceState(state, title, newUrl);
}
/**
* @return {?}
*/
forward() { throw new Error('Not implemented'); }
/**
* @return {?}
*/
back() { throw new Error('Not implemented'); }
}
ServerPlatformLocation.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ServerPlatformLocation.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] },] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [INITIAL_CONFIG,] },] },
];
/**
* @param {?} fn
* @return {?}
*/
function scheduleMicroTask(fn) {
Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
const EMPTY_ARRAY = [];
class ServerRendererFactory2 {
/**
* @param {?} ngZone
* @param {?} document
* @param {?} sharedStylesHost
*/
constructor(ngZone, document, sharedStylesHost) {
this.ngZone = ngZone;
this.document = document;
this.sharedStylesHost = sharedStylesHost;
this.rendererByCompId = new Map();
this.schema = new DomElementSchemaRegistry();
this.defaultRenderer = new DefaultServerRenderer2(document, ngZone, this.schema);
}
/**
* @param {?} element
* @param {?} type
* @return {?}
*/
createRenderer(element, type) {
if (!element || !type) {
return this.defaultRenderer;
}
switch (type.encapsulation) {
case ViewEncapsulation.Native:
case ViewEncapsulation.Emulated: {
let /** @type {?} */ renderer = this.rendererByCompId.get(type.id);
if (!renderer) {
renderer = new EmulatedEncapsulationServerRenderer2(this.document, this.ngZone, this.sharedStylesHost, this.schema, type);
this.rendererByCompId.set(type.id, renderer);
}
(/** @type {?} */ (renderer)).applyToHost(element);
return renderer;
}
case ViewEncapsulation.Native:
throw new Error('Native encapsulation is not supported on the server!');
default: {
if (!this.rendererByCompId.has(type.id)) {
const /** @type {?} */ styles = ɵflattenStyles(type.id, type.styles, []);
this.sharedStylesHost.addStyles(styles);
this.rendererByCompId.set(type.id, this.defaultRenderer);
}
return this.defaultRenderer;
}
}
}
/**
* @return {?}
*/
begin() { }
/**
* @return {?}
*/
end() { }
}
ServerRendererFactory2.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ServerRendererFactory2.ctorParameters = () => [
{ type: NgZone, },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] },] },
{ type: ɵSharedStylesHost, },
];
class DefaultServerRenderer2 {
/**
* @param {?} document
* @param {?} ngZone
* @param {?} schema
*/
constructor(document, ngZone, schema) {
this.document = document;
this.ngZone = ngZone;
this.schema = schema;
this.data = Object.create(null);
}
/**
* @return {?}
*/
destroy() { }
/**
* @param {?} name
* @param {?=} namespace
* @param {?=} debugInfo
* @return {?}
*/
createElement(name, namespace, debugInfo) {
if (namespace) {
return ɵgetDOM().createElementNS(ɵNAMESPACE_URIS[namespace], name);
}
return ɵgetDOM().createElement(name);
}
/**
* @param {?} value
* @param {?=} debugInfo
* @return {?}
*/
createComment(value, debugInfo) { return ɵgetDOM().createComment(value); }
/**
* @param {?} value
* @param {?=} debugInfo
* @return {?}
*/
createText(value, debugInfo) { return ɵgetDOM().createTextNode(value); }
/**
* @param {?} parent
* @param {?} newChild
* @return {?}
*/
appendChild(parent, newChild) { ɵgetDOM().appendChild(parent, newChild); }
/**
* @param {?} parent
* @param {?} newChild
* @param {?} refChild
* @return {?}
*/
insertBefore(parent, newChild, refChild) {
if (parent) {
ɵgetDOM().insertBefore(parent, refChild, newChild);
}
}
/**
* @param {?} parent
* @param {?} oldChild
* @return {?}
*/
removeChild(parent, oldChild) {
if (parent) {
ɵgetDOM().removeChild(parent, oldChild);
}
}
/**
* @param {?} selectorOrNode
* @param {?=} debugInfo
* @return {?}
*/
selectRootElement(selectorOrNode, debugInfo) {
let /** @type {?} */ el;
if (typeof selectorOrNode === 'string') {
el = ɵgetDOM().querySelector(this.document, selectorOrNode);
if (!el) {
throw new Error(`The selector "${selectorOrNode}" did not match any elements`);
}
}
else {
el = selectorOrNode;
}
ɵgetDOM().clearNodes(el);
return el;
}
/**
* @param {?} node
* @return {?}
*/
parentNode(node) { return ɵgetDOM().parentElement(node); }
/**
* @param {?} node
* @return {?}
*/
nextSibling(node) { return ɵgetDOM().nextSibling(node); }
/**
* @param {?} el
* @param {?} name
* @param {?} value
* @param {?=} namespace
* @return {?}
*/
setAttribute(el, name, value, namespace) {
if (namespace) {
ɵgetDOM().setAttributeNS(el, ɵNAMESPACE_URIS[namespace], namespace + ':' + name, value);
}
else {
ɵgetDOM().setAttribute(el, name, value);
}
}
/**
* @param {?} el
* @param {?} name
* @param {?=} namespace
* @return {?}
*/
removeAttribute(el, name, namespace) {
if (namespace) {
ɵgetDOM().removeAttributeNS(el, ɵNAMESPACE_URIS[namespace], name);
}
else {
ɵgetDOM().removeAttribute(el, name);
}
}
/**
* @param {?} el
* @param {?} name
* @return {?}
*/
addClass(el, name) { ɵgetDOM().addClass(el, name); }
/**
* @param {?} el
* @param {?} name
* @return {?}
*/
removeClass(el, name) { ɵgetDOM().removeClass(el, name); }
/**
* @param {?} el
* @param {?} style
* @param {?} value
* @param {?} flags
* @return {?}
*/
setStyle(el, style, value, flags) {
ɵgetDOM().setStyle(el, style, value);
}
/**
* @param {?} el
* @param {?} style
* @param {?} flags
* @return {?}
*/
removeStyle(el, style, flags) {
ɵgetDOM().removeStyle(el, style);
}
/**
* @param {?} tagName
* @param {?} propertyName
* @return {?}
*/
_isSafeToReflectProperty(tagName, propertyName) {
return this.schema.securityContext(tagName, propertyName, true) ===
this.schema.securityContext(tagName, propertyName, false);
}
/**
* @param {?} el
* @param {?} name
* @param {?} value
* @return {?}
*/
setProperty(el, name, value) {
checkNoSyntheticProp(name, 'property');
ɵgetDOM().setProperty(el, name, value);
// Mirror property values for known HTML element properties in the attributes.
const /** @type {?} */ tagName = (/** @type {?} */ (el.tagName)).toLowerCase();
if (value != null && (typeof value === 'number' || typeof value == 'string') &&
this.schema.hasElement(tagName, EMPTY_ARRAY) &&
this.schema.hasProperty(tagName, name, EMPTY_ARRAY) &&
this._isSafeToReflectProperty(tagName, name)) {
this.setAttribute(el, name, value.toString());
}
}
/**
* @param {?} node
* @param {?} value
* @return {?}
*/
setValue(node, value) { ɵgetDOM().setText(node, value); }
/**
* @param {?} target
* @param {?} eventName
* @param {?} callback
* @return {?}
*/
listen(target, eventName, callback) {
// Note: We are not using the EventsPlugin here as this is not needed
// to run our tests.
checkNoSyntheticProp(eventName, 'listener');
const /** @type {?} */ el = typeof target === 'string' ? ɵgetDOM().getGlobalEventTarget(this.document, target) : target;
const /** @type {?} */ outsideHandler = (event) => this.ngZone.runGuarded(() => callback(event));
return this.ngZone.runOutsideAngular(() => /** @type {?} */ (ɵgetDOM().onAndCancel(el, eventName, outsideHandler)));
}
}
const AT_CHARCODE = '@'.charCodeAt(0);
/**
* @param {?} name
* @param {?} nameKind
* @return {?}
*/
function checkNoSyntheticProp(name, nameKind) {
if (name.charCodeAt(0) === AT_CHARCODE) {
throw new Error(`Found the synthetic ${nameKind} ${name}. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.`);
}
}
class EmulatedEncapsulationServerRenderer2 extends DefaultServerRenderer2 {
/**
* @param {?} document
* @param {?} ngZone
* @param {?} sharedStylesHost
* @param {?} schema
* @param {?} component
*/
constructor(document, ngZone, sharedStylesHost, schema, component) {
super(document, ngZone, schema);
this.component = component;
const /** @type {?} */ styles = ɵflattenStyles(component.id, component.styles, []);
sharedStylesHost.addStyles(styles);
this.contentAttr = ɵshimContentAttribute(component.id);
this.hostAttr = ɵshimHostAttribute(component.id);
}
/**
* @param {?} element
* @return {?}
*/
applyToHost(element) { super.setAttribute(element, this.hostAttr, ''); }
/**
* @param {?} parent
* @param {?} name
* @return {?}
*/
createElement(parent, name) {
const /** @type {?} */ el = super.createElement(parent, name);
super.setAttribute(el, this.contentAttr, '');
return el;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
class ServerStylesHost extends ɵSharedStylesHost {
/**
* @param {?} doc
* @param {?} transitionId
*/
constructor(doc, transitionId) {
super();
this.doc = doc;
this.transitionId = transitionId;
this.head = null;
this.head = ɵgetDOM().getElementsByTagName(doc, 'head')[0];
}
/**
* @param {?} style
* @return {?}
*/
_addStyle(style) {
let /** @type {?} */ adapter = ɵgetDOM();
const /** @type {?} */ el = adapter.createElement('style');
adapter.setText(el, style);
if (!!this.transitionId) {
adapter.setAttribute(el, 'ng-transition', this.transitionId);
}
adapter.appendChild(this.head, el);
}
/**
* @param {?} additions
* @return {?}
*/
onStylesAdded(additions) { additions.forEach(style => this._addStyle(style)); }
}
ServerStylesHost.decorators = [
{ type: Injectable },
];
/** @nocollapse */
ServerStylesHost.ctorParameters = () => [
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] },] },
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [ɵTRANSITION_ID,] },] },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
const INTERNAL_SERVER_PLATFORM_PROVIDERS = [
{ provide: DOCUMENT, useFactory: _document, deps: [Injector] },
{ provide: PLATFORM_ID, useValue: ɵPLATFORM_SERVER_ID },
{ provide: PLATFORM_INITIALIZER, useFactory: initDominoAdapter, multi: true, deps: [Injector] }, {
provide: PlatformLocation,
useClass: ServerPlatformLocation,
deps: [DOCUMENT, [Optional, INITIAL_CONFIG]]
},
{ provide: PlatformState, deps: [DOCUMENT] },
// Add special provider that allows multiple instances of platformServer* to be created.
{ provide: ɵALLOW_MULTIPLE_PLATFORMS, useValue: true }
];
/**
* @param {?} injector
* @return {?}
*/
function initDominoAdapter(injector) {
return () => { DominoAdapter.makeCurrent(); };
}
/**
* @param {?} renderer
* @param {?} engine
* @param {?} zone
* @return {?}
*/
function instantiateServerRendererFactory(renderer, engine, zone) {
return new ɵAnimationRendererFactory(renderer, engine, zone);
}
const SERVER_RENDER_PROVIDERS = [
ServerRendererFactory2,
{
provide: RendererFactory2,
useFactory: instantiateServerRendererFactory,
deps: [ServerRendererFactory2, ɵAnimationEngine, NgZone]
},
ServerStylesHost,
{ provide: ɵSharedStylesHost, useExisting: ServerStylesHost },
];
/**
* The ng module for the server.
*
* \@experimental
*/
class ServerModule {
}
ServerModule.decorators = [
{ type: NgModule, args: [{
exports: [BrowserModule],
imports: [HttpModule, HttpClientModule, NoopAnimationsModule],
providers: [
SERVER_RENDER_PROVIDERS,
SERVER_HTTP_PROVIDERS,
{ provide: Testability, useValue: null },
],
},] },
];
/** @nocollapse */
ServerModule.ctorParameters = () => [];
/**
* @param {?} injector
* @return {?}
*/
function _document(injector) {
let /** @type {?} */ config = injector.get(INITIAL_CONFIG, null);
if (config && config.document) {
return parseDocument(config.document, config.url);
}
else {
return ɵgetDOM().createHtmlDocument();
}
}
/**
* \@experimental
*/
const platformServer = createPlatformFactory(platformCore, 'server', INTERNAL_SERVER_PLATFORM_PROVIDERS);
/**
* The server platform that supports the runtime compiler.
*
* \@experimental
*/
const platformDynamicServer = createPlatformFactory(ɵplatformCoreDynamic, 'serverDynamic', INTERNAL_SERVER_PLATFORM_PROVIDERS);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @param {?} doc
* @param {?} appId
* @param {?} transferStore
* @return {?}
*/
function serializeTransferStateFactory(doc, appId, transferStore) {
return () => {
const /** @type {?} */ script = doc.createElement('script');
script.id = appId + '-state';
script.setAttribute('type', 'application/json');
script.textContent = ɵescapeHtml(transferStore.toJson());
doc.body.appendChild(script);
};
}
/**
* NgModule to install on the server side while using the `TransferState` to transfer state from
* server to client.
*
* \@experimental
*/
class ServerTransferStateModule {
}
ServerTransferStateModule.decorators = [
{ type: NgModule, args: [{
providers: [
TransferState, {
provide: BEFORE_APP_SERIALIZED,
useFactory: serializeTransferStateFactory,
deps: [DOCUMENT, APP_ID, TransferState],
multi: true,
}
]
},] },
];
/** @nocollapse */
ServerTransferStateModule.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @param {?} platformFactory
* @param {?} options
* @return {?}
*/
function _getPlatform(platformFactory, options) {
const /** @type {?} */ extraProviders = options.extraProviders ? options.extraProviders : [];
return platformFactory([
{ provide: INITIAL_CONFIG, useValue: { document: options.document, url: options.url } },
extraProviders
]);
}
/**
* @template T
* @param {?} platform
* @param {?} moduleRefPromise
* @return {?}
*/
function _render(platform, moduleRefPromise) {
return moduleRefPromise.then((moduleRef) => {
const /** @type {?} */ transitionId = moduleRef.injector.get(ɵTRANSITION_ID, null);
if (!transitionId) {
throw new Error(`renderModule[Factory]() requires the use of BrowserModule.withServerTransition() to ensure
the server-rendered app can be properly bootstrapped into a client app.`);
}
const /** @type {?} */ applicationRef = moduleRef.injector.get(ApplicationRef);
return toPromise
.call(first.call(filter.call(applicationRef.isStable, (isStable) => isStable)))
.then(() => {
const /** @type {?} */ platformState = platform.injector.get(PlatformState);
// Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.
const /** @type {?} */ callbacks = moduleRef.injector.get(BEFORE_APP_SERIALIZED, null);
if (callbacks) {
for (const /** @type {?} */ callback of callbacks) {
try {
callback();
}
catch (/** @type {?} */ e) {
// Ignore exceptions.
console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);
}
}
}
const /** @type {?} */ output = platformState.renderToString();
platform.destroy();
return output;
});
});
}
/**
* Renders a Module to string.
*
* `document` is the full document HTML of the page to render, as a string.
* `url` is the URL for the current render request.
* `extraProviders` are the platform level providers for the current render request.
*
* Do not use this in a production server environment. Use pre-compiled {\@link NgModuleFactory} with
* {\@link renderModuleFactory} instead.
*
* \@experimental
* @template T
* @param {?} module
* @param {?} options
* @return {?}
*/
function renderModule(module, options) {
const /** @type {?} */ platform = _getPlatform(platformDynamicServer, options);
return _render(platform, platform.bootstrapModule(module));
}
/**
* Renders a {\@link NgModuleFactory} to string.
*
* `document` is the full document HTML of the page to render, as a string.
* `url` is the URL for the current render request.
* `extraProviders` are the platform level providers for the current render request.
*
* \@experimental
* @template T
* @param {?} moduleFactory
* @param {?} options
* @return {?}
*/
function renderModuleFactory(moduleFactory, options) {
const /** @type {?} */ platform = _getPlatform(platformServer, options);
return _render(platform, platform.bootstrapModuleFactory(moduleFactory));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
/**
* \@stable
*/
const VERSION = new Version('5.0.0-rc.8');
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @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
*/
/**
* @module
* @description
* Entry point for all public APIs of this package.
*/
// This file only reexports content of the `src` folder. Keep it that way.
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
export { PlatformState, ServerModule, platformDynamicServer, platformServer, BEFORE_APP_SERIALIZED, INITIAL_CONFIG, ServerTransferStateModule, renderModule, renderModuleFactory, VERSION, INTERNAL_SERVER_PLATFORM_PROVIDERS as ɵINTERNAL_SERVER_PLATFORM_PROVIDERS, SERVER_RENDER_PROVIDERS as ɵSERVER_RENDER_PROVIDERS, ServerRendererFactory2 as ɵServerRendererFactory2, SERVER_HTTP_PROVIDERS as ɵh, ServerXhr as ɵd, ServerXsrfStrategy as ɵe, httpFactory as ɵf, zoneWrappedInterceptingHandler as ɵg, instantiateServerRendererFactory as ɵa, ServerStylesHost as ɵc, serializeTransferStateFactory as ɵb };
//# sourceMappingURL=platform-server.js.map