Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): add DOCUMENT_REF API #55315

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions goldens/public-api/common/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ export class DecimalPipe implements PipeTransform {
// @public
export const DOCUMENT: InjectionToken<Document>;

// @public
export const DOCUMENT_REF: InjectionToken<ElementRef<Document>>;

// @public
export function formatCurrency(value: number, locale: string, currency: string, currencyCode?: string, digitsInfo?: string): string;

Expand Down
5 changes: 4 additions & 1 deletion goldens/public-api/platform-server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { ApplicationRef } from '@angular/core';
import { ElementRef } from '@angular/core';
import { EnvironmentProviders } from '@angular/core';
import * as i0 from '@angular/core';
import * as i1 from '@angular/common/http';
Expand Down Expand Up @@ -34,8 +35,10 @@ export const platformServer: (extraProviders?: StaticProvider[] | undefined) =>

// @public
export class PlatformState {
constructor(_doc: any);
constructor(_doc: ElementRef<Document>);
// @deprecated
getDocument(): any;
getDocumentRef(): ElementRef<Document>;
renderToString(): string;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<PlatformState, never>;
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export {
NgTemplateOutlet,
NgComponentOutlet,
} from './directives/index';
export {DOCUMENT} from './dom_tokens';
export {DOCUMENT, DOCUMENT_REF} from './dom_tokens';
export {
AsyncPipe,
DatePipe,
Expand Down
12 changes: 11 additions & 1 deletion packages/common/src/dom_tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {InjectionToken} from '@angular/core';
import {ElementRef, InjectionToken} from '@angular/core';

/**
* A DI Token representing the main rendering context.
Expand All @@ -16,3 +16,13 @@ import {InjectionToken} from '@angular/core';
* @publicApi
*/
export const DOCUMENT = new InjectionToken<Document>(ngDevMode ? 'DocumentToken' : '');

/**
* A DI token representing a reference to the main the DOM Document.
* Unlike `DOCUMENT`, this always has a value even if DOM emulation is disabled.
*
* @publicApi
*/
export const DOCUMENT_REF = new InjectionToken<ElementRef<Document>>(
ngDevMode ? 'DocumentRefToken' : '',
);
11 changes: 6 additions & 5 deletions packages/platform-server/src/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT, LocationChangeEvent, LocationChangeListener, PlatformLocation, ɵgetDOM as getDOM} from '@angular/common';
import {Inject, Injectable, Optional, ɵWritable as Writable} from '@angular/core';
import {DOCUMENT_REF, LocationChangeEvent, LocationChangeListener, PlatformLocation, ɵgetDOM as getDOM} from '@angular/common';
import {ElementRef, Inject, Injectable, Optional, ɵWritable as Writable} from '@angular/core';
import {Subject} from 'rxjs';

import {INITIAL_CONFIG, PlatformConfig} from './tokens';
Expand Down Expand Up @@ -51,7 +51,8 @@ export class ServerPlatformLocation implements PlatformLocation {
private _hashUpdate = new Subject<LocationChangeEvent>();

constructor(
@Inject(DOCUMENT) private _doc: any, @Optional() @Inject(INITIAL_CONFIG) _config: any) {
@Inject(DOCUMENT_REF) private _doc: ElementRef<Document>,
@Optional() @Inject(INITIAL_CONFIG) _config: any) {
const config = _config as PlatformConfig | null;
if (!config) {
return;
Expand All @@ -64,12 +65,12 @@ export class ServerPlatformLocation implements PlatformLocation {
this.pathname = url.pathname;
this.search = url.search;
this.hash = url.hash;
this.href = _doc.location.href;
this.href = _doc.nativeElement.location.href;
}
}

getBaseHrefFromDOM(): string {
return getDOM().getBaseHref(this._doc)!;
return getDOM().getBaseHref(this._doc.nativeElement)!;
}

onPopState(fn: LocationChangeListener): VoidFunction {
Expand Down
17 changes: 13 additions & 4 deletions packages/platform-server/src/platform_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT} from '@angular/common';
import {Inject, Injectable} from '@angular/core';
import {DOCUMENT_REF} from '@angular/common';
import {ElementRef, Inject, Injectable} from '@angular/core';

import {serializeDocument} from './domino_adapter';

Expand All @@ -18,19 +18,28 @@ import {serializeDocument} from './domino_adapter';
*/
@Injectable()
export class PlatformState {
constructor(@Inject(DOCUMENT) private _doc: any) {}
constructor(@Inject(DOCUMENT_REF) private _doc: ElementRef<Document>) {}

/**
* Renders the current state of the platform to string.
*/
renderToString(): string {
return serializeDocument(this._doc);
return serializeDocument(this._doc.nativeElement);
}

/**
* Returns the current DOM state.
*
* @deprecated Use `getDocumentRef` instead.
*/
getDocument(): any {
return this._doc.nativeElement;
}

/**
* Returns a reference to the current DOM Document.
*/
getDocumentRef(): ElementRef<Document> {
return this._doc;
}
}
17 changes: 11 additions & 6 deletions packages/platform-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT, PlatformLocation, ViewportScroller, ɵgetDOM as getDOM, ɵNullViewportScroller as NullViewportScroller, ɵPLATFORM_SERVER_ID as PLATFORM_SERVER_ID} from '@angular/common';
import {DOCUMENT, DOCUMENT_REF, PlatformLocation, ViewportScroller, ɵgetDOM as getDOM, ɵNullViewportScroller as NullViewportScroller, ɵPLATFORM_SERVER_ID as PLATFORM_SERVER_ID} from '@angular/common';
import {HttpClientModule} from '@angular/common/http';
import {createPlatformFactory, Injector, NgModule, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, platformCore, PlatformRef, Provider, StaticProvider, Testability, ɵALLOW_MULTIPLE_PLATFORMS as ALLOW_MULTIPLE_PLATFORMS, ɵsetDocument, ɵTESTABILITY as TESTABILITY} from '@angular/core';
import {createPlatformFactory, ElementRef, Injector, NgModule, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, platformCore, PlatformRef, Provider, StaticProvider, Testability, ɵALLOW_MULTIPLE_PLATFORMS as ALLOW_MULTIPLE_PLATFORMS, ɵsetDocument, ɵTESTABILITY as TESTABILITY} from '@angular/core';
import {BrowserModule, EVENT_MANAGER_PLUGINS} from '@angular/platform-browser';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';

Expand All @@ -21,14 +21,15 @@ import {INITIAL_CONFIG, PlatformConfig} from './tokens';
import {TRANSFER_STATE_SERIALIZATION_PROVIDERS} from './transfer_state';

export const INTERNAL_SERVER_PLATFORM_PROVIDERS: StaticProvider[] = [
{provide: DOCUMENT, useFactory: _document, deps: [Injector]},
{provide: DOCUMENT_REF, useFactory: _document, deps: [Injector]},
{provide: DOCUMENT, useFactory: getDocument, deps: [DOCUMENT_REF]},
{provide: PLATFORM_ID, useValue: PLATFORM_SERVER_ID},
{provide: PLATFORM_INITIALIZER, useFactory: initDominoAdapter, multi: true}, {
provide: PlatformLocation,
useClass: ServerPlatformLocation,
deps: [DOCUMENT, [Optional, INITIAL_CONFIG]]
deps: [DOCUMENT_REF, [Optional, INITIAL_CONFIG]]
},
{provide: PlatformState, deps: [DOCUMENT]},
{provide: PlatformState, deps: [DOCUMENT_REF]},
// Add special provider that allows multiple instances of platformServer* to be created.
{provide: ALLOW_MULTIPLE_PLATFORMS, useValue: true}
];
Expand Down Expand Up @@ -76,7 +77,11 @@ function _document(injector: Injector) {
}
// Tell ivy about the global document
ɵsetDocument(document);
return document;
return new ElementRef(document);
}

function getDocument(docRef: ElementRef<Document>) {
return docRef.nativeElement;
}

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/platform-server/src/server_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT, ɵgetDOM as getDOM} from '@angular/common';
import {Inject, Injectable} from '@angular/core';
import {DOCUMENT_REF, ɵgetDOM as getDOM} from '@angular/common';
import {ElementRef, Inject, Injectable} from '@angular/core';
import {EventManagerPlugin} from '@angular/platform-browser';

@Injectable()
export class ServerEventManagerPlugin extends EventManagerPlugin {
constructor(@Inject(DOCUMENT) private doc: any) {
super(doc);
constructor(@Inject(DOCUMENT_REF) private doc: ElementRef<Document>) {
super(doc.nativeElement);
}

// Handle all events on the server.
Expand Down
10 changes: 6 additions & 4 deletions packages/platform-server/src/transfer_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@
* found in the LICENSE file at https://angular.io/license
*/

import {DOCUMENT} from '@angular/common';
import {APP_ID, Provider, TransferState} from '@angular/core';
import {DOCUMENT_REF} from '@angular/common';
import {APP_ID, ElementRef, Provider, TransferState} from '@angular/core';

import {BEFORE_APP_SERIALIZED} from './tokens';

export const TRANSFER_STATE_SERIALIZATION_PROVIDERS: Provider[] = [
{
provide: BEFORE_APP_SERIALIZED,
useFactory: serializeTransferStateFactory,
deps: [DOCUMENT, APP_ID, TransferState],
deps: [DOCUMENT_REF, APP_ID, TransferState],
multi: true,
},
];

function serializeTransferStateFactory(doc: Document, appId: string, transferStore: TransferState) {
function serializeTransferStateFactory(
docRef: ElementRef<Document>, appId: string, transferStore: TransferState) {
return () => {
// The `.toJSON` here causes the `onSerialize` callbacks to be called.
// These callbacks can be used to provide the value for a given key.
Expand All @@ -32,6 +33,7 @@ function serializeTransferStateFactory(doc: Document, appId: string, transferSto
return;
}

const doc = docRef.nativeElement;
const script = doc.createElement('script');
script.id = appId + '-state';
script.setAttribute('type', 'application/json');
Expand Down