Skip to content

Commit 8675b8d

Browse files
committed
fix: cleanup public api of platform-server
BREAKING CHANGE: Parse5Adapter is no longer exported as public API, use serverBootstrap() Parse5Adapter is an implementation detail not a public API Closes angular#9237 Closes angular#9205
1 parent 279e816 commit 8675b8d

File tree

10 files changed

+137
-144
lines changed

10 files changed

+137
-144
lines changed

modules/@angular/common/src/location/platform_location.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export abstract class PlatformLocation {
2929
abstract onPopState(fn: UrlChangeListener): void;
3030
abstract onHashChange(fn: UrlChangeListener): void;
3131

32-
/* abstract */ get pathname(): string { return null; }
33-
/* abstract */ get search(): string { return null; }
34-
/* abstract */ get hash(): string { return null; }
32+
get pathname(): string { return null; }
33+
get search(): string { return null; }
34+
get hash(): string { return null; }
3535

3636
abstract replaceState(state: any, title: string, url: string): void;
3737

modules/@angular/compiler-cli/integrationtest/test/animate_spec.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ require('zone.js/dist/long-stack-trace-zone.js');
44

55
import {AnimateCmpNgFactory} from '../src/animate.ngfactory';
66
import {ReflectiveInjector, DebugElement, getDebugNode, lockRunMode} from '@angular/core';
7-
import {browserPlatform, BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
7+
import {serverPlatform} from '@angular/platform-server';
8+
import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
9+
810

911
// Need to lock the mode explicitely as this test is not using Angular's testing framework.
1012
lockRunMode();
@@ -17,8 +19,8 @@ describe('template codegen output', () => {
1719
}
1820

1921
it('should apply the animate states to the element', (done) => {
20-
const appInjector =
21-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
22+
const appInjector = ReflectiveInjector.resolveAndCreate(
23+
BROWSER_APP_PROVIDERS, serverPlatform().injector);
2224
var comp = AnimateCmpNgFactory.create(appInjector);
2325
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
2426

@@ -45,8 +47,8 @@ describe('template codegen output', () => {
4547
});
4648

4749
it('should apply the default animate state to the element', (done) => {
48-
const appInjector =
49-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
50+
const appInjector = ReflectiveInjector.resolveAndCreate(
51+
BROWSER_APP_PROVIDERS, serverPlatform().injector);
5052
var comp = AnimateCmpNgFactory.create(appInjector);
5153
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
5254

modules/@angular/compiler-cli/integrationtest/test/basic_spec.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import * as path from 'path';
1010
import {BasicNgFactory} from '../src/basic.ngfactory';
1111
import {MyComp} from '../src/a/multiple_components';
1212
import {ReflectiveInjector, DebugElement, getDebugNode, lockRunMode} from '@angular/core';
13-
import {browserPlatform, BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
13+
import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
14+
import {serverPlatform} from '@angular/platform-server';
1415

1516
// Need to lock the mode explicitely as this test is not using Angular's testing framework.
1617
lockRunMode();
@@ -40,14 +41,14 @@ describe('template codegen output', () => {
4041

4142
it('should be able to create the basic component', () => {
4243
const appInjector =
43-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
44+
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector);
4445
var comp = BasicNgFactory.create(appInjector);
4546
expect(comp.instance).toBeTruthy();
4647
});
4748

4849
it('should support ngIf', () => {
4950
const appInjector =
50-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
51+
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector);
5152
var comp = BasicNgFactory.create(appInjector);
5253
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
5354
expect(debugElement.children.length).toBe(2);
@@ -60,7 +61,7 @@ describe('template codegen output', () => {
6061

6162
it('should support ngFor', () => {
6263
const appInjector =
63-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
64+
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector);
6465
var comp = BasicNgFactory.create(appInjector);
6566
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
6667
expect(debugElement.children.length).toBe(2);

modules/@angular/compiler-cli/integrationtest/test/projection_spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {DebugElement, ReflectiveInjector, getDebugNode, lockRunMode} from '@angular/core';
2-
import {BROWSER_APP_PROVIDERS, By, browserPlatform} from '@angular/platform-browser';
2+
import {BROWSER_APP_PROVIDERS, By} from '@angular/platform-browser';
3+
import {serverPlatform} from '@angular/platform-server';
34

45
import {CompWithProjection} from '../src/projection';
56
import {MainCompNgFactory} from '../src/projection.ngfactory';
@@ -10,7 +11,7 @@ lockRunMode();
1011
describe('content projection', () => {
1112
it('should support basic content projection', () => {
1213
const appInjector =
13-
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, browserPlatform().injector);
14+
ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS, serverPlatform().injector);
1415
var mainComp = MainCompNgFactory.create(appInjector);
1516

1617
var debugElement = <DebugElement>getDebugNode(mainComp.location.nativeElement);

modules/@angular/platform-server/core_private.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import {__core_private__ as r, __core_private_types__ as t} from '@angular/core';
22

3-
export type NoOpAnimationPlayer = t.NoOpAnimationPlayer;
4-
export var NoOpAnimationPlayer: typeof t.NoOpAnimationPlayer = r.NoOpAnimationPlayer;
5-
export type AnimationPlayer = t.AnimationPlayer;
6-
export var AnimationPlayer: typeof t.AnimationPlayer = r.AnimationPlayer;
3+
export var reflector: typeof t.reflector = r.reflector;
4+
export var ReflectionCapabilities: typeof t.ReflectionCapabilities = r.ReflectionCapabilities;
5+
export var wtfInit: typeof t.wtfInit = r.wtfInit;
76
export type NoOpAnimationDriver = t.NoOpAnimationDriver;
87
export var NoOpAnimationDriver: typeof t.NoOpAnimationDriver = r.NoOpAnimationDriver;
98
export type AnimationDriver = t.AnimationDriver;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
// TODO: vsavkin add SERVER_PROVIDERS and SERVER_APP_PROVIDERS
1+
// TODO: vsavkin add SERVER_PROVIDERS and SERVER_APPLICATION_PROVIDERS
22
export 'package:angular2/src/platform/server/html_adapter.dart';
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
// TODO: vsavkin add SERVER_PROVIDERS and SERVER_APP_PROVIDERS
2-
export {Parse5DomAdapter} from './src/parse5_adapter';
1+
export {SERVER_PLATFORM_PROVIDERS, serverBootstrap, serverPlatform} from './src/server';
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import {PlatformLocation} from '@angular/common';
2+
import {ComponentRef, OpaqueToken, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, PlatformRef, ReflectiveInjector, Type, assertPlatform, coreLoadAndBootstrap, createPlatform, getPlatform} from '@angular/core';
3+
4+
import {ReflectionCapabilities, reflector, wtfInit} from '../core_private';
5+
6+
import {Parse5DomAdapter} from './parse5_adapter';
7+
8+
const SERVER_PLATFORM_MARKER = new OpaqueToken('ServerPlatformMarker');
9+
10+
function notSupported(feature: string): Error {
11+
throw new Error(`platform-server does not support '${feature}'.`);
12+
}
13+
14+
class ServerPlatformLocation extends PlatformLocation {
15+
getBaseHrefFromDOM(): string { throw notSupported('getBaseHrefFromDOM'); };
16+
onPopState(fn: any): void { notSupported('onPopState'); };
17+
onHashChange(fn: any): void { notSupported('onHashChange'); };
18+
get pathname(): string { throw notSupported('pathname'); }
19+
get search(): string { throw notSupported('search'); }
20+
get hash(): string { throw notSupported('hash'); }
21+
replaceState(state: any, title: string, url: string): void { notSupported('replaceState'); };
22+
pushState(state: any, title: string, url: string): void { notSupported('pushState'); };
23+
forward(): void { notSupported('forward'); };
24+
back(): void { notSupported('back'); };
25+
}
26+
27+
/**
28+
* A set of providers to initialize the Angular platform in a server.
29+
*
30+
* Used automatically by `serverBootstrap`, or can be passed to {@link platform}.
31+
* @experimental
32+
*/
33+
export const SERVER_PLATFORM_PROVIDERS: Array<any /*Type | Provider | any[]*/> = [
34+
{provide: SERVER_PLATFORM_MARKER, useValue: true}, PLATFORM_COMMON_PROVIDERS,
35+
{provide: PLATFORM_INITIALIZER, useValue: initParse5Adapter, multi: true},
36+
{provide: PlatformLocation, useClass: ServerPlatformLocation}
37+
];
38+
39+
40+
function initParse5Adapter() {
41+
Parse5DomAdapter.makeCurrent();
42+
wtfInit();
43+
}
44+
45+
/**
46+
* @experimental
47+
*/
48+
export function serverPlatform(): PlatformRef {
49+
if (!getPlatform()) {
50+
createPlatform(ReflectiveInjector.resolveAndCreate(SERVER_PLATFORM_PROVIDERS));
51+
}
52+
return assertPlatform(SERVER_PLATFORM_MARKER);
53+
}
54+
55+
/**
56+
* Used to bootstrap Angular in server environment (such as node).
57+
*
58+
* This version of bootstrap only creates platform injector and does not define anything for
59+
* application injector. It is expected that application providers are imported from other
60+
* packages such as `@angular/platform-browser` or `@angular/platform-browser-dynamic`.
61+
*
62+
* ```
63+
* import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
64+
* import {BROWSER_APP_COMPILER_PROVIDERS} from '@angular/platform-browser-dynamic';
65+
*
66+
* serverBootstrap(..., [BROWSER_APP_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS])
67+
* ```
68+
*
69+
* @experimental
70+
*/
71+
export function serverBootstrap(
72+
appComponentType: Type,
73+
providers: Array<any /*Type | Provider | any[]*/>): Promise<ComponentRef<any>> {
74+
reflector.reflectionCapabilities = new ReflectionCapabilities();
75+
var appInjector = ReflectiveInjector.resolveAndCreate(providers, serverPlatform().injector);
76+
return coreLoadAndBootstrap(appComponentType, appInjector);
77+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {Component, disposePlatform} from '@angular/core';
2+
import {afterEach, async, beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing';
3+
import {BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
4+
import {BROWSER_APP_COMPILER_PROVIDERS} from '@angular/platform-browser-dynamic';
5+
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
6+
import {serverBootstrap} from '@angular/platform-server';
7+
8+
function writeBody(html: string): any {
9+
var dom = getDOM();
10+
var doc = dom.defaultDoc();
11+
var body = dom.querySelector(doc, 'body');
12+
dom.setInnerHTML(body, html);
13+
return body;
14+
}
15+
16+
export function main() {
17+
if (getDOM().supportsDOMEvents()) return; // NODE only
18+
19+
describe('platform-server integration', () => {
20+
21+
afterEach(() => disposePlatform());
22+
23+
it('should bootstrap', async(() => {
24+
var body = writeBody('<app></app>');
25+
serverBootstrap(MyServerApp, [
26+
BROWSER_APP_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS
27+
]).then(() => { expect(getDOM().getText(body)).toEqual('Works!'); });
28+
}));
29+
});
30+
}
31+
32+
@Component({selector: 'app', template: `Works!`})
33+
class MyServerApp {
34+
}

tools/public_api_guard/public_api_spec.ts

Lines changed: 3 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,129 +1663,9 @@ const PLATFORM_BROWSER_DYNAMIC_TESTING = [
16631663

16641664

16651665
const PLATFORM_SERVER = [
1666-
'Parse5DomAdapter',
1667-
'Parse5DomAdapter.addClass(element:any, className:string):any',
1668-
'Parse5DomAdapter.adoptNode(node:any):any',
1669-
'Parse5DomAdapter.animate(element:any, keyframes:any[], options:any):any',
1670-
'Parse5DomAdapter.appendChild(el:any, node:any):any',
1671-
'Parse5DomAdapter.attributeMap(element:any):Map<string, string>',
1672-
'Parse5DomAdapter.attrToPropMap:any',
1673-
'Parse5DomAdapter.cancelAnimationFrame(id:number):any',
1674-
'Parse5DomAdapter.childNodes(el:any):Node[]',
1675-
'Parse5DomAdapter.childNodesAsList(el:any):any[]',
1676-
'Parse5DomAdapter.classList(element:any):string[]',
1677-
'Parse5DomAdapter.clearNodes(el:any):any',
1678-
'Parse5DomAdapter.clone(node:Node):Node',
1679-
'Parse5DomAdapter.content(node:any):string',
1680-
'Parse5DomAdapter.createComment(text:string):Comment',
1681-
'Parse5DomAdapter.createElement(tagName:any):HTMLElement',
1682-
'Parse5DomAdapter.createElementNS(ns:any, tagName:any):HTMLElement',
1683-
'Parse5DomAdapter.createEvent(eventType:string):Event',
1684-
'Parse5DomAdapter.createHtmlDocument():Document',
1685-
'Parse5DomAdapter.createMouseEvent(eventType:any):Event',
1686-
'Parse5DomAdapter.createScriptTag(attrName:string, attrValue:string):HTMLElement',
1687-
'Parse5DomAdapter.createShadowRoot(el:any):HTMLElement',
1688-
'Parse5DomAdapter.createStyleElement(css:string):HTMLStyleElement',
1689-
'Parse5DomAdapter.createTemplate(html:any):HTMLElement',
1690-
'Parse5DomAdapter.createTextNode(text:string):Text',
1691-
'Parse5DomAdapter.defaultDoc():Document',
1692-
'Parse5DomAdapter.dispatchEvent(el:any, evt:any):any',
1693-
'Parse5DomAdapter.elementMatches(node:any, selector:string, matcher:any=null):boolean',
1694-
'Parse5DomAdapter.firstChild(el:any):Node',
1695-
'Parse5DomAdapter.getAnimationPrefix():string',
1696-
'Parse5DomAdapter.getAttribute(element:any, attribute:string):string',
1697-
'Parse5DomAdapter.getAttributeNS(element:any, ns:string, attribute:string):string',
1698-
'Parse5DomAdapter.getBaseHref():string',
1699-
'Parse5DomAdapter.getBoundingClientRect(el:any):any',
1700-
'Parse5DomAdapter.getChecked(el:any):boolean',
1701-
'Parse5DomAdapter.getComputedStyle(el:any):any',
1702-
'Parse5DomAdapter.getCookie(name:string):string',
1703-
'Parse5DomAdapter.getData(el:any, name:string):string',
1704-
'Parse5DomAdapter.getDistributedNodes(el:any):Node[]',
1705-
'Parse5DomAdapter.getElementsByClassName(element:any, name:string):HTMLElement[]',
1706-
'Parse5DomAdapter.getElementsByTagName(element:any, name:string):HTMLElement[]',
1707-
'Parse5DomAdapter.getEventKey(event:any):string',
1708-
'Parse5DomAdapter.getGlobalEventTarget(target:string):any',
1709-
'Parse5DomAdapter.getHistory():History',
1710-
'Parse5DomAdapter.getHost(el:any):string',
1711-
'Parse5DomAdapter.getHref(el:any):string',
1712-
'Parse5DomAdapter.getInnerHTML(el:any):string',
1713-
'Parse5DomAdapter.getLocation():Location',
1714-
'Parse5DomAdapter.getOuterHTML(el:any):string',
1715-
'Parse5DomAdapter.getProperty(el:any, name:string):any',
1716-
'Parse5DomAdapter.getShadowRoot(el:any):Element',
1717-
'Parse5DomAdapter.getStyle(element:any, styleName:string):string',
1718-
'Parse5DomAdapter.getTemplateContent(el:any):Node',
1719-
'Parse5DomAdapter.getText(el:any, isRecursive?:boolean):string',
1720-
'Parse5DomAdapter.getTitle():string',
1721-
'Parse5DomAdapter.getTransitionEnd():string',
1722-
'Parse5DomAdapter.getUserAgent():string',
1723-
'Parse5DomAdapter.getValue(el:any):string',
1724-
'Parse5DomAdapter.getXHR():Type',
1725-
'Parse5DomAdapter.hasAttribute(element:any, attribute:string):boolean',
1726-
'Parse5DomAdapter.hasAttributeNS(element:any, ns:string, attribute:string):boolean',
1727-
'Parse5DomAdapter.hasClass(element:any, className:string):boolean',
1728-
'Parse5DomAdapter.hasProperty(element:any, name:string):boolean',
1729-
'Parse5DomAdapter.hasShadowRoot(node:any):boolean',
1730-
'Parse5DomAdapter.hasStyle(element:any, styleName:string, styleValue:string=null):boolean',
1731-
'Parse5DomAdapter.importIntoDoc(node:any):any',
1732-
'Parse5DomAdapter.insertAfter(el:any, node:any):any',
1733-
'Parse5DomAdapter.insertAllBefore(el:any, nodes:any):any',
1734-
'Parse5DomAdapter.insertBefore(el:any, node:any):any',
1735-
'Parse5DomAdapter.invoke(el:Element, methodName:string, args:any[]):any',
1736-
'Parse5DomAdapter.isCommentNode(node:any):boolean',
1737-
'Parse5DomAdapter.isElementNode(node:any):boolean',
1738-
'Parse5DomAdapter.isPrevented(evt:any):boolean',
1739-
'Parse5DomAdapter.isShadowRoot(node:any):boolean',
1740-
'Parse5DomAdapter.isTemplateElement(el:any):boolean',
1741-
'Parse5DomAdapter.isTextNode(node:any):boolean',
1742-
'Parse5DomAdapter.log(error:any):any',
1743-
'Parse5DomAdapter.logError(error:any):any',
1744-
'Parse5DomAdapter.logGroup(error:any):any',
1745-
'Parse5DomAdapter.logGroupEnd():any',
1746-
'Parse5DomAdapter.makeCurrent():any',
1747-
'Parse5DomAdapter.nextSibling(el:any):Node',
1748-
'Parse5DomAdapter.nodeName(node:any):string',
1749-
'Parse5DomAdapter.nodeValue(node:any):string',
1750-
'Parse5DomAdapter.on(el:any, evt:any, listener:any):any',
1751-
'Parse5DomAdapter.onAndCancel(el:any, evt:any, listener:any):Function',
1752-
'Parse5DomAdapter.parentElement(el:any):Node',
1753-
'Parse5DomAdapter.parse(templateHtml:string):any',
1754-
'Parse5DomAdapter.performanceNow():number',
1755-
'Parse5DomAdapter.preventDefault(evt:any):any',
1756-
'Parse5DomAdapter.query(selector:any):any',
1757-
'Parse5DomAdapter.querySelector(el:any, selector:string):any',
1758-
'Parse5DomAdapter.querySelectorAll(el:any, selector:string):any[]',
1759-
'Parse5DomAdapter.remove(el:any):HTMLElement',
1760-
'Parse5DomAdapter.removeAttribute(element:any, attribute:string):any',
1761-
'Parse5DomAdapter.removeAttributeNS(element:any, ns:string, name:string):any',
1762-
'Parse5DomAdapter.removeChild(el:any, node:any):any',
1763-
'Parse5DomAdapter.removeClass(element:any, className:string):any',
1764-
'Parse5DomAdapter.removeStyle(element:any, styleName:string):any',
1765-
'Parse5DomAdapter.replaceChild(el:any, newNode:any, oldNode:any):any',
1766-
'Parse5DomAdapter.requestAnimationFrame(callback:any):number',
1767-
'Parse5DomAdapter.resetBaseElement():void',
1768-
'Parse5DomAdapter.resolveAndSetHref(el:any, baseUrl:string, href:string):any',
1769-
'Parse5DomAdapter.setAttribute(element:any, attribute:string, value:string):any',
1770-
'Parse5DomAdapter.setAttributeNS(element:any, ns:string, attribute:string, value:string):any',
1771-
'Parse5DomAdapter.setChecked(el:any, value:boolean):any',
1772-
'Parse5DomAdapter.setCookie(name:string, value:string):any',
1773-
'Parse5DomAdapter.setData(el:any, name:string, value:string):any',
1774-
'Parse5DomAdapter.setGlobalVar(path:string, value:any):any',
1775-
'Parse5DomAdapter.setInnerHTML(el:any, value:any):any',
1776-
'Parse5DomAdapter.setProperty(el:any, name:string, value:any):any',
1777-
'Parse5DomAdapter.setStyle(element:any, styleName:string, styleValue:string):any',
1778-
'Parse5DomAdapter.setText(el:any, value:string):any',
1779-
'Parse5DomAdapter.setTitle(newTitle:string):any',
1780-
'Parse5DomAdapter.setValue(el:any, value:string):any',
1781-
'Parse5DomAdapter.supportsAnimation():boolean',
1782-
'Parse5DomAdapter.supportsCookies():boolean',
1783-
'Parse5DomAdapter.supportsDOMEvents():boolean',
1784-
'Parse5DomAdapter.supportsNativeShadowDOM():boolean',
1785-
'Parse5DomAdapter.supportsWebAnimation():boolean',
1786-
'Parse5DomAdapter.tagName(element:any):string',
1787-
'Parse5DomAdapter.templateAwareRoot(el:any):any',
1788-
'Parse5DomAdapter.type(node:any):string',
1666+
'const SERVER_PLATFORM_PROVIDERS:Array<any>',
1667+
'serverBootstrap(appComponentType:Type, providers:Array<any>):Promise<ComponentRef<any>>',
1668+
'serverPlatform():PlatformRef',
17891669
];
17901670

17911671
const PLATFORM_SERVER_TESTING = [

0 commit comments

Comments
 (0)