@angular/common
Version:
Angular - commonly needed directives and services
667 lines • 90 kB
JavaScript
/**
* @license
* Copyright Google LLC 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
*/
// Prevents deletion of `Event` from `globalThis` during module loading.
const Event = globalThis.Event;
/**
* Fake implementation of user agent history and navigation behavior. This is a
* high-fidelity implementation of browser behavior that attempts to emulate
* things like traversal delay.
*/
export class FakeNavigation {
/** Equivalent to `navigation.currentEntry`. */
get currentEntry() {
return this.entriesArr[this.currentEntryIndex];
}
get canGoBack() {
return this.currentEntryIndex > 0;
}
get canGoForward() {
return this.currentEntryIndex < this.entriesArr.length - 1;
}
constructor(window, startURL) {
this.window = window;
/**
* The fake implementation of an entries array. Only same-document entries
* allowed.
*/
this.entriesArr = [];
/**
* The current active entry index into `entriesArr`.
*/
this.currentEntryIndex = 0;
/**
* The current navigate event.
*/
this.navigateEvent = undefined;
/**
* A Map of pending traversals, so that traversals to the same entry can be
* re-used.
*/
this.traversalQueue = new Map();
/**
* A Promise that resolves when the previous traversals have finished. Used to
* simulate the cross-process communication necessary for traversals.
*/
this.nextTraversal = Promise.resolve();
/**
* A prospective current active entry index, which includes unresolved
* traversals. Used by `go` to determine where navigations are intended to go.
*/
this.prospectiveEntryIndex = 0;
/**
* A test-only option to make traversals synchronous, rather than emulate
* cross-process communication.
*/
this.synchronousTraversals = false;
/** Whether to allow a call to setInitialEntryForTesting. */
this.canSetInitialEntry = true;
/** `EventTarget` to dispatch events. */
this.eventTarget = this.window.document.createElement('div');
/** The next unique id for created entries. Replace recreates this id. */
this.nextId = 0;
/** The next unique key for created entries. Replace inherits this id. */
this.nextKey = 0;
/** Whether this fake is disposed. */
this.disposed = false;
// First entry.
this.setInitialEntryForTesting(startURL);
}
/**
* Sets the initial entry.
*/
setInitialEntryForTesting(url, options = { historyState: null }) {
if (!this.canSetInitialEntry) {
throw new Error('setInitialEntryForTesting can only be called before any ' +
'navigation has occurred');
}
const currentInitialEntry = this.entriesArr[0];
this.entriesArr[0] = new FakeNavigationHistoryEntry(new URL(url).toString(), {
index: 0,
key: currentInitialEntry?.key ?? String(this.nextKey++),
id: currentInitialEntry?.id ?? String(this.nextId++),
sameDocument: true,
historyState: options?.historyState,
state: options.state,
});
}
/** Returns whether the initial entry is still eligible to be set. */
canSetInitialEntryForTesting() {
return this.canSetInitialEntry;
}
/**
* Sets whether to emulate traversals as synchronous rather than
* asynchronous.
*/
setSynchronousTraversalsForTesting(synchronousTraversals) {
this.synchronousTraversals = synchronousTraversals;
}
/** Equivalent to `navigation.entries()`. */
entries() {
return this.entriesArr.slice();
}
/** Equivalent to `navigation.navigate()`. */
navigate(url, options) {
const fromUrl = new URL(this.currentEntry.url);
const toUrl = new URL(url, this.currentEntry.url);
let navigationType;
if (!options?.history || options.history === 'auto') {
// Auto defaults to push, but if the URLs are the same, is a replace.
if (fromUrl.toString() === toUrl.toString()) {
navigationType = 'replace';
}
else {
navigationType = 'push';
}
}
else {
navigationType = options.history;
}
const hashChange = isHashChange(fromUrl, toUrl);
const destination = new FakeNavigationDestination({
url: toUrl.toString(),
state: options?.state,
sameDocument: hashChange,
historyState: null,
});
const result = new InternalNavigationResult();
this.userAgentNavigate(destination, result, {
navigationType,
cancelable: true,
canIntercept: true,
// Always false for navigate().
userInitiated: false,
hashChange,
info: options?.info,
});
return {
committed: result.committed,
finished: result.finished,
};
}
/** Equivalent to `history.pushState()`. */
pushState(data, title, url) {
this.pushOrReplaceState('push', data, title, url);
}
/** Equivalent to `history.replaceState()`. */
replaceState(data, title, url) {
this.pushOrReplaceState('replace', data, title, url);
}
pushOrReplaceState(navigationType, data, _title, url) {
const fromUrl = new URL(this.currentEntry.url);
const toUrl = url ? new URL(url, this.currentEntry.url) : fromUrl;
const hashChange = isHashChange(fromUrl, toUrl);
const destination = new FakeNavigationDestination({
url: toUrl.toString(),
sameDocument: true,
historyState: data,
});
const result = new InternalNavigationResult();
this.userAgentNavigate(destination, result, {
navigationType,
cancelable: true,
canIntercept: true,
// Always false for pushState() or replaceState().
userInitiated: false,
hashChange,
skipPopState: true,
});
}
/** Equivalent to `navigation.traverseTo()`. */
traverseTo(key, options) {
const fromUrl = new URL(this.currentEntry.url);
const entry = this.findEntry(key);
if (!entry) {
const domException = new DOMException('Invalid key', 'InvalidStateError');
const committed = Promise.reject(domException);
const finished = Promise.reject(domException);
committed.catch(() => { });
finished.catch(() => { });
return {
committed,
finished,
};
}
if (entry === this.currentEntry) {
return {
committed: Promise.resolve(this.currentEntry),
finished: Promise.resolve(this.currentEntry),
};
}
if (this.traversalQueue.has(entry.key)) {
const existingResult = this.traversalQueue.get(entry.key);
return {
committed: existingResult.committed,
finished: existingResult.finished,
};
}
const hashChange = isHashChange(fromUrl, new URL(entry.url, this.currentEntry.url));
const destination = new FakeNavigationDestination({
url: entry.url,
state: entry.getState(),
historyState: entry.getHistoryState(),
key: entry.key,
id: entry.id,
index: entry.index,
sameDocument: entry.sameDocument,
});
this.prospectiveEntryIndex = entry.index;
const result = new InternalNavigationResult();
this.traversalQueue.set(entry.key, result);
this.runTraversal(() => {
this.traversalQueue.delete(entry.key);
this.userAgentNavigate(destination, result, {
navigationType: 'traverse',
cancelable: true,
canIntercept: true,
// Always false for traverseTo().
userInitiated: false,
hashChange,
info: options?.info,
});
});
return {
committed: result.committed,
finished: result.finished,
};
}
/** Equivalent to `navigation.back()`. */
back(options) {
if (this.currentEntryIndex === 0) {
const domException = new DOMException('Cannot go back', 'InvalidStateError');
const committed = Promise.reject(domException);
const finished = Promise.reject(domException);
committed.catch(() => { });
finished.catch(() => { });
return {
committed,
finished,
};
}
const entry = this.entriesArr[this.currentEntryIndex - 1];
return this.traverseTo(entry.key, options);
}
/** Equivalent to `navigation.forward()`. */
forward(options) {
if (this.currentEntryIndex === this.entriesArr.length - 1) {
const domException = new DOMException('Cannot go forward', 'InvalidStateError');
const committed = Promise.reject(domException);
const finished = Promise.reject(domException);
committed.catch(() => { });
finished.catch(() => { });
return {
committed,
finished,
};
}
const entry = this.entriesArr[this.currentEntryIndex + 1];
return this.traverseTo(entry.key, options);
}
/**
* Equivalent to `history.go()`.
* Note that this method does not actually work precisely to how Chrome
* does, instead choosing a simpler model with less unexpected behavior.
* Chrome has a few edge case optimizations, for instance with repeated
* `back(); forward()` chains it collapses certain traversals.
*/
go(direction) {
const targetIndex = this.prospectiveEntryIndex + direction;
if (targetIndex >= this.entriesArr.length || targetIndex < 0) {
return;
}
this.prospectiveEntryIndex = targetIndex;
this.runTraversal(() => {
// Check again that destination is in the entries array.
if (targetIndex >= this.entriesArr.length || targetIndex < 0) {
return;
}
const fromUrl = new URL(this.currentEntry.url);
const entry = this.entriesArr[targetIndex];
const hashChange = isHashChange(fromUrl, new URL(entry.url, this.currentEntry.url));
const destination = new FakeNavigationDestination({
url: entry.url,
state: entry.getState(),
historyState: entry.getHistoryState(),
key: entry.key,
id: entry.id,
index: entry.index,
sameDocument: entry.sameDocument,
});
const result = new InternalNavigationResult();
this.userAgentNavigate(destination, result, {
navigationType: 'traverse',
cancelable: true,
canIntercept: true,
// Always false for go().
userInitiated: false,
hashChange,
});
});
}
/** Runs a traversal synchronously or asynchronously */
runTraversal(traversal) {
if (this.synchronousTraversals) {
traversal();
return;
}
// Each traversal occupies a single timeout resolution.
// This means that Promises added to commit and finish should resolve
// before the next traversal.
this.nextTraversal = this.nextTraversal.then(() => {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
traversal();
});
});
});
}
/** Equivalent to `navigation.addEventListener()`. */
addEventListener(type, callback, options) {
this.eventTarget.addEventListener(type, callback, options);
}
/** Equivalent to `navigation.removeEventListener()`. */
removeEventListener(type, callback, options) {
this.eventTarget.removeEventListener(type, callback, options);
}
/** Equivalent to `navigation.dispatchEvent()` */
dispatchEvent(event) {
return this.eventTarget.dispatchEvent(event);
}
/** Cleans up resources. */
dispose() {
// Recreate eventTarget to release current listeners.
// `document.createElement` because NodeJS `EventTarget` is incompatible with Domino's `Event`.
this.eventTarget = this.window.document.createElement('div');
this.disposed = true;
}
/** Returns whether this fake is disposed. */
isDisposed() {
return this.disposed;
}
/** Implementation for all navigations and traversals. */
userAgentNavigate(destination, result, options) {
// The first navigation should disallow any future calls to set the initial
// entry.
this.canSetInitialEntry = false;
if (this.navigateEvent) {
this.navigateEvent.cancel(new DOMException('Navigation was aborted', 'AbortError'));
this.navigateEvent = undefined;
}
const navigateEvent = createFakeNavigateEvent({
navigationType: options.navigationType,
cancelable: options.cancelable,
canIntercept: options.canIntercept,
userInitiated: options.userInitiated,
hashChange: options.hashChange,
signal: result.signal,
destination,
info: options.info,
sameDocument: destination.sameDocument,
skipPopState: options.skipPopState,
result,
userAgentCommit: () => {
this.userAgentCommit();
},
});
this.navigateEvent = navigateEvent;
this.eventTarget.dispatchEvent(navigateEvent);
navigateEvent.dispatchedNavigateEvent();
if (navigateEvent.commitOption === 'immediate') {
navigateEvent.commit(/* internal= */ true);
}
}
/** Implementation to commit a navigation. */
userAgentCommit() {
if (!this.navigateEvent) {
return;
}
const from = this.currentEntry;
if (!this.navigateEvent.sameDocument) {
const error = new Error('Cannot navigate to a non-same-document URL.');
this.navigateEvent.cancel(error);
throw error;
}
if (this.navigateEvent.navigationType === 'push' ||
this.navigateEvent.navigationType === 'replace') {
this.userAgentPushOrReplace(this.navigateEvent.destination, {
navigationType: this.navigateEvent.navigationType,
});
}
else if (this.navigateEvent.navigationType === 'traverse') {
this.userAgentTraverse(this.navigateEvent.destination);
}
this.navigateEvent.userAgentNavigated(this.currentEntry);
const currentEntryChangeEvent = createFakeNavigationCurrentEntryChangeEvent({ from, navigationType: this.navigateEvent.navigationType });
this.eventTarget.dispatchEvent(currentEntryChangeEvent);
if (!this.navigateEvent.skipPopState) {
const popStateEvent = createPopStateEvent({
state: this.navigateEvent.destination.getHistoryState(),
});
this.window.dispatchEvent(popStateEvent);
}
}
/** Implementation for a push or replace navigation. */
userAgentPushOrReplace(destination, { navigationType }) {
if (navigationType === 'push') {
this.currentEntryIndex++;
this.prospectiveEntryIndex = this.currentEntryIndex;
}
const index = this.currentEntryIndex;
const key = navigationType === 'push' ? String(this.nextKey++) : this.currentEntry.key;
const entry = new FakeNavigationHistoryEntry(destination.url, {
id: String(this.nextId++),
key,
index,
sameDocument: true,
state: destination.getState(),
historyState: destination.getHistoryState(),
});
if (navigationType === 'push') {
this.entriesArr.splice(index, Infinity, entry);
}
else {
this.entriesArr[index] = entry;
}
}
/** Implementation for a traverse navigation. */
userAgentTraverse(destination) {
this.currentEntryIndex = destination.index;
}
/** Utility method for finding entries with the given `key`. */
findEntry(key) {
for (const entry of this.entriesArr) {
if (entry.key === key)
return entry;
}
return undefined;
}
set onnavigate(_handler) {
throw new Error('unimplemented');
}
get onnavigate() {
throw new Error('unimplemented');
}
set oncurrententrychange(_handler) {
throw new Error('unimplemented');
}
get oncurrententrychange() {
throw new Error('unimplemented');
}
set onnavigatesuccess(_handler) {
throw new Error('unimplemented');
}
get onnavigatesuccess() {
throw new Error('unimplemented');
}
set onnavigateerror(_handler) {
throw new Error('unimplemented');
}
get onnavigateerror() {
throw new Error('unimplemented');
}
get transition() {
throw new Error('unimplemented');
}
updateCurrentEntry(_options) {
throw new Error('unimplemented');
}
reload(_options) {
throw new Error('unimplemented');
}
}
/**
* Fake equivalent of `NavigationHistoryEntry`.
*/
export class FakeNavigationHistoryEntry {
constructor(url, { id, key, index, sameDocument, state, historyState, }) {
this.url = url;
// tslint:disable-next-line:no-any
this.ondispose = null;
this.id = id;
this.key = key;
this.index = index;
this.sameDocument = sameDocument;
this.state = state;
this.historyState = historyState;
}
getState() {
// Budget copy.
return this.state ? JSON.parse(JSON.stringify(this.state)) : this.state;
}
getHistoryState() {
// Budget copy.
return this.historyState ? JSON.parse(JSON.stringify(this.historyState)) : this.historyState;
}
addEventListener(type, callback, options) {
throw new Error('unimplemented');
}
removeEventListener(type, callback, options) {
throw new Error('unimplemented');
}
dispatchEvent(event) {
throw new Error('unimplemented');
}
}
/**
* Create a fake equivalent of `NavigateEvent`. This is not a class because ES5
* transpiled JavaScript cannot extend native Event.
*/
function createFakeNavigateEvent({ cancelable, canIntercept, userInitiated, hashChange, navigationType, signal, destination, info, sameDocument, skipPopState, result, userAgentCommit, }) {
const event = new Event('navigate', { bubbles: false, cancelable });
event.canIntercept = canIntercept;
event.userInitiated = userInitiated;
event.hashChange = hashChange;
event.navigationType = navigationType;
event.signal = signal;
event.destination = destination;
event.info = info;
event.downloadRequest = null;
event.formData = null;
event.sameDocument = sameDocument;
event.skipPopState = skipPopState;
event.commitOption = 'immediate';
let handlerFinished = undefined;
let interceptCalled = false;
let dispatchedNavigateEvent = false;
let commitCalled = false;
event.intercept = function (options) {
interceptCalled = true;
event.sameDocument = true;
const handler = options?.handler;
if (handler) {
handlerFinished = handler();
}
if (options?.commit) {
event.commitOption = options.commit;
}
if (options?.focusReset !== undefined || options?.scroll !== undefined) {
throw new Error('unimplemented');
}
};
event.scroll = function () {
throw new Error('unimplemented');
};
event.commit = function (internal = false) {
if (!internal && !interceptCalled) {
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': intercept() must be ` +
`called before commit().`, 'InvalidStateError');
}
if (!dispatchedNavigateEvent) {
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() may not be ` +
`called during event dispatch.`, 'InvalidStateError');
}
if (commitCalled) {
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() already ` +
`called.`, 'InvalidStateError');
}
commitCalled = true;
userAgentCommit();
};
// Internal only.
event.cancel = function (reason) {
result.committedReject(reason);
result.finishedReject(reason);
};
// Internal only.
event.dispatchedNavigateEvent = function () {
dispatchedNavigateEvent = true;
if (event.commitOption === 'after-transition') {
// If handler finishes before commit, call commit.
handlerFinished?.then(() => {
if (!commitCalled) {
event.commit(/* internal */ true);
}
}, () => { });
}
Promise.all([result.committed, handlerFinished])
.then(([entry]) => {
result.finishedResolve(entry);
}, (reason) => {
result.finishedReject(reason);
});
};
// Internal only.
event.userAgentNavigated = function (entry) {
result.committedResolve(entry);
};
return event;
}
/**
* Create a fake equivalent of `NavigationCurrentEntryChange`. This does not use
* a class because ES5 transpiled JavaScript cannot extend native Event.
*/
function createFakeNavigationCurrentEntryChangeEvent({ from, navigationType, }) {
const event = new Event('currententrychange', {
bubbles: false,
cancelable: false,
});
event.from = from;
event.navigationType = navigationType;
return event;
}
/**
* Create a fake equivalent of `PopStateEvent`. This does not use a class
* because ES5 transpiled JavaScript cannot extend native Event.
*/
function createPopStateEvent({ state }) {
const event = new Event('popstate', {
bubbles: false,
cancelable: false,
});
event.state = state;
return event;
}
/**
* Fake equivalent of `NavigationDestination`.
*/
export class FakeNavigationDestination {
constructor({ url, sameDocument, historyState, state, key = null, id = null, index = -1, }) {
this.url = url;
this.sameDocument = sameDocument;
this.state = state;
this.historyState = historyState;
this.key = key;
this.id = id;
this.index = index;
}
getState() {
return this.state;
}
getHistoryState() {
return this.historyState;
}
}
/** Utility function to determine whether two UrlLike have the same hash. */
function isHashChange(from, to) {
return (to.hash !== from.hash && to.hostname === from.hostname && to.pathname === from.pathname &&
to.search === from.search);
}
/** Internal utility class for representing the result of a navigation. */
class InternalNavigationResult {
get signal() {
return this.abortController.signal;
}
constructor() {
this.abortController = new AbortController();
this.committed = new Promise((resolve, reject) => {
this.committedResolve = resolve;
this.committedReject = reject;
});
this.finished = new Promise(async (resolve, reject) => {
this.finishedResolve = resolve;
this.finishedReject = (reason) => {
reject(reason);
this.abortController.abort(reason);
};
});
// All rejections are handled.
this.committed.catch(() => { });
this.finished.catch(() => { });
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFrZV9uYXZpZ2F0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3Rlc3Rpbmcvc3JjL25hdmlnYXRpb24vZmFrZV9uYXZpZ2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILHdFQUF3RTtBQUN4RSxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO0FBRS9COzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQXdEekIsK0NBQStDO0lBQy9DLElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsSUFBSSxTQUFTO1FBQ1gsT0FBTyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELFlBQTZCLE1BQWMsRUFBRSxRQUF5QjtRQUF6QyxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBcEUzQzs7O1dBR0c7UUFDYyxlQUFVLEdBQWlDLEVBQUUsQ0FBQztRQUUvRDs7V0FFRztRQUNLLHNCQUFpQixHQUFHLENBQUMsQ0FBQztRQUU5Qjs7V0FFRztRQUNLLGtCQUFhLEdBQXdDLFNBQVMsQ0FBQztRQUV2RTs7O1dBR0c7UUFDYyxtQkFBYyxHQUFHLElBQUksR0FBRyxFQUFvQyxDQUFDO1FBRTlFOzs7V0FHRztRQUNLLGtCQUFhLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRTFDOzs7V0FHRztRQUNLLDBCQUFxQixHQUFHLENBQUMsQ0FBQztRQUVsQzs7O1dBR0c7UUFDSywwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFF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