Skip to content

Commit

Permalink
Refactoring of location implementation (it now conforms to both Locat…
Browse files Browse the repository at this point in the history
…ion and PlatformLocation and can therefore be used in either context)
  • Loading branch information
clbond committed Apr 17, 2017
1 parent db3404b commit 7528327
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 53 deletions.
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "angular-ssr",
"version": "0.1.71",
"version": "0.1.72",
"description": "Angular server-side rendering implementation",
"main": "build/index.js",
"typings": "build/index.d.ts",
Expand Down
4 changes: 2 additions & 2 deletions source/application/builder/tests/from-source.ts
@@ -1,8 +1,8 @@
import {join} from 'path';

import {ApplicationBuilderFromSource} from '../from-source';
import {Project} from './../../project';
import {absoluteFile, absolutePath, pathFromRandomId} from './../../../filesystem';
import {Project} from '../../project';
import {absoluteFile, absolutePath, pathFromRandomId} from '../../../filesystem';
import {templateDocument, getApplicationProject, getApplicationRoot} from '../../../test/fixtures';

describe('ApplicationFromSource', () => {
Expand Down
2 changes: 1 addition & 1 deletion source/application/compiler/options.ts
Expand Up @@ -13,7 +13,7 @@ import {CompilerException} from '../../exception';

import {ModuleDeclaration, Project} from '../project';

import {discoverRootModule} from './../static';
import {discoverRootModule} from '../static';

export interface CompilationOptions {
ts: CompilerOptions;
Expand Down
2 changes: 1 addition & 1 deletion source/application/compiler/webpack/compiler.ts
Expand Up @@ -7,7 +7,7 @@ import {createProgram} from 'typescript';
import {Provider} from '@angular/core';

import {ApplicationCompiler} from '../compiler';
import {CompilerException} from './../../../exception';
import {CompilerException} from '../../../exception';
import {ConfigurationLoader} from './config';
import {ModuleLoader} from '../loader';
import {Project} from '../../project';
Expand Down
2 changes: 1 addition & 1 deletion source/application/compiler/webpack/loader.ts
Expand Up @@ -3,7 +3,7 @@ import {NgModuleFactory} from '@angular/core';
import {join} from 'path';

import {CompilerException} from '../../../exception';
import {ModuleDeclaration, Project} from './../../project';
import {ModuleDeclaration, Project} from '../../project';
import {ModuleLoader} from '../loader';

export type Chunk = {name: string, files: Array<string>};
Expand Down
2 changes: 1 addition & 1 deletion source/application/static/find.ts
Expand Up @@ -8,7 +8,7 @@ import {

import {dirname, relative, resolve} from 'path';

import {ModuleDeclaration} from './../project';
import {ModuleDeclaration} from '../project';

import {traverse} from './traverse';

Expand Down
2 changes: 1 addition & 1 deletion source/application/static/modules/collect.ts
Expand Up @@ -8,7 +8,7 @@ import {

import {ModuleDeclaration} from '../../project';
import {PathReference} from '../../../filesystem';
import {isExternalModule} from './../predicates';
import {isExternalModule} from '../predicates';
import {importClause} from '../find';
import {traverse} from '../traverse';

Expand Down
8 changes: 7 additions & 1 deletion source/exception.ts
Expand Up @@ -23,7 +23,13 @@ export class AggregateException extends Exception {

export class NotImplementedException extends Exception {
constructor() {
super(chalk.red('Not implemented'));
super('Not implemented');
}
}

export class NotSupportedException extends Exception {
constructor() {
super('This operation is not supported in a browserless context and never will be');
}
}

Expand Down
47 changes: 46 additions & 1 deletion source/platform/location/location.ts
Expand Up @@ -9,10 +9,14 @@ import {
PlatformLocation,
} from '@angular/common';

import url = require('url');

import {DocumentContainer, RequestUri} from '../document';

import {NotSupportedException} from '../../exception';

@Injectable()
export class LocationImpl implements PlatformLocation, OnDestroy {
export class LocationImpl implements Location, PlatformLocation, OnDestroy {
initializationPromise: Promise<void>;

private readonly destruction = new Array<() => void>();
Expand All @@ -32,10 +36,42 @@ export class LocationImpl implements PlatformLocation, OnDestroy {
this.initialized();
}

assign(uri: string) {
throw new NotSupportedException();
}

replace(uri: string) {
throw new NotSupportedException();
}

reload() {
throw new NotSupportedException();
}

get href(): string {
return this.requestUri;
}

get host(): string {
return this.parsed(u => u.host);
}

get hostname(): string {
return this.parsed(u => u.hostname);
}

get origin(): string {
return this.requestUri;
}

get port(): string {
return this.parsed(u => u.port);
}

get protocol(): string {
return this.parsed(u => u.protocol);
}

getBaseHrefFromDOM(): string {
const element = this.documentContainer.document.querySelector('base');
if (element == null) {
Expand Down Expand Up @@ -87,4 +123,13 @@ export class LocationImpl implements PlatformLocation, OnDestroy {
ngOnDestroy() {
this.destruction.forEach(d => d());
}

private parsed<T>(fn: (uri: url.Url) => T): T {
try {
return fn(url.parse(this.href));
}
catch (exception) {
return null;
}
}
}
23 changes: 23 additions & 0 deletions source/platform/zone/assertions.ts
@@ -0,0 +1,23 @@
import chalk = require('chalk');

import {PlatformException} from '../../exception';

const assertionFailure = (identifier: string) => {
console.error(chalk.red(`This application is executing in a context where '${identifier}' is defined`));
console.error(chalk.red(`This is completely unexpected and unsupported`));
console.error(chalk.red('Please ensure that you have not imported a conflicting DOM library like jsdom!'));

throw new PlatformException(`Running in a browserless environment but '${identifier}' is non-null!`);
}

if (typeof window !== 'undefined') {
assertionFailure('window');
}

if (typeof document !== 'undefined') {
assertionFailure('document');
}

if (typeof Zone === 'undefined') {
throw new PlatformException(`Zone is undefined (import zone.js into this process)`);
}
28 changes: 10 additions & 18 deletions source/platform/zone/environment.ts
@@ -1,20 +1,12 @@
import {PlatformLocation} from '@angular/common';
import './assertions';

import {ConsoleCollector} from '../collectors';
import {DocumentContainer} from '../document';
import {PlatformException} from '../../exception';
import {LocationImpl} from '../location/location';
import {RuntimeModuleLoader} from '../module/runtime-loader';
import {bootWindow} from '../../runtime/browser-emulation';
import {injectableFromZone} from './injector-map';

if (typeof window !== 'undefined' || typeof document !== 'undefined') {
throw new PlatformException('Executing in a NodeJS environment but window and document are non-null!');
}

if (typeof Zone === 'undefined') {
throw new PlatformException(`You must import zone.js into this process (Zone is undefined)`);
}

export const baseConsole = console;

Object.defineProperties(global, {
Expand All @@ -25,20 +17,20 @@ Object.defineProperties(global, {
},
document: {
get: () => {
const doc = injectableFromZone(Zone.current, DocumentContainer);
if (doc) {
return doc.document;
let container: {document} = injectableFromZone(Zone.current, DocumentContainer);
if (container == null) {
container = bootWindow;
}
return bootWindow.document;
return container.document;
}
},
location: {
get: () => {
const location = injectableFromZone(Zone.current, PlatformLocation);
if (location) {
return location;
let location: Location = injectableFromZone(Zone.current, LocationImpl);
if (location == null) {
location = window.location;
}
return bootWindow.location;
return location;
}
},
navigator: {
Expand Down
33 changes: 18 additions & 15 deletions source/platform/zone/fork.ts
@@ -1,20 +1,23 @@
export const forkZone = <R>(documentTemplate: string, requestUri: string, execute: () => Promise<R>): Promise<R> => {
return new Promise((resolve, reject) => {
const zone = Zone.current.fork({
name: requestUri,
properties: {
documentTemplate,
requestUri,
},
onHandleError: function (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error) {
reject(error);
let failure = (exception: Error) => true; // rethrow

const zone = Zone.current.fork({
name: requestUri,
properties: {
documentTemplate,
requestUri,
},
onHandleError: function (parentZoneDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error) {
return failure(error);
}
});

return false;
}
});
return new Promise((resolve, reject) => {
failure = exception => {
reject(exception);
return false;
};

return zone.runGuarded(() => {
execute().then(r => resolve(r)).catch(exception => reject(exception));
}) as R;
return zone.runGuarded(() => Promise.resolve(execute()).then(resolve).catch(reject)) as R;
});
}
10 changes: 3 additions & 7 deletions source/runtime/browser-emulation/control.ts
@@ -1,15 +1,11 @@
import {NotImplementedException} from '../../exception';
import {NotSupportedException} from '../../exception';

import domino = require('domino');

function stop() {
throw new NotImplementedException();
}
function stop() {}

function close() {}

function open(url: string, name: string, specs, replace) {
return domino.createWindow(String(), url);
throw new NotSupportedException();
};

export const bindControl = (target: () => Window) => ({open, close: close.bind(target), stop});
4 changes: 2 additions & 2 deletions source/runtime/browser-emulation/interaction.ts
@@ -1,9 +1,9 @@
import {NotImplementedException} from '../../exception';
import {NotSupportedException} from '../../exception';

const alert = (message: string) => {};

const confirm = (message) => {
throw new NotImplementedException();
throw new NotSupportedException();
}

const print = () => {};
Expand Down
2 changes: 1 addition & 1 deletion source/transformation/type-to-function.ts
@@ -1,6 +1,6 @@
import {Injector, ReflectiveInjector, Type} from '@angular/core';

import {isInjectable} from './../platform/module/metadata/decorators';
import {isInjectable} from '../platform/module/metadata/decorators';

export type InjectorFunction<R> = (injector: Injector, ...args) => R;

Expand Down

0 comments on commit 7528327

Please sign in to comment.