@angular/common
Version:
Angular - commonly needed directives and services
668 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, baseURI) {
this.window = window;
this.baseURI = baseURI;
/**
* 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('.');
}
/**
* 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(options.absoluteUrl ? url : new URL(url, this.baseURI).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, this.baseURI);
const toUrl = new URL(url, this.baseURI);
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, this.baseURI);
const toUrl = url ? new URL(url, this.baseURI) : 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, this.baseURI);
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.baseURI));
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, this.baseURI);
const entry = this.entriesArr[targetIndex];
const hashChange = isHashChange(fromUrl, new URL(entry.url, this.baseURI));
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFrZV9uYXZpZ2F0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL3Rlc3Rpbmcvc3JjL25hdmlnYXRpb24vZmFrZV9uYXZpZ2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILHdFQUF3RTtBQUN4RSxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO0FBRS9COzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sY0FBYztJQXdEekIsK0NBQStDO0lBQy9DLElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsSUFBSSxTQUFTO1FBQ1gsT0FBTyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELFlBQTZCLE1BQWMsRUFBbUIsT0FBZTtRQUFoRCxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQW1CLFlBQU8sR0FBUCxPQUFPLENBQVE7UUFwRTdFOzs7V0FHRztRQUNjLGVBQVUsR0FBaUMsRUFBRSxDQUFDO1FBRS9EOztXQUVHO1FBQ0ssc0JBQWlCLEdBQUcsQ0FBQyxDQUFDO1FBRTlCOztXQUVHO1FBQ0ssa0JBQWEsR0FBd0MsU0FBUyxDQUFDO1FBRXZFOzs7V0FHRztRQUNjLG1CQUFjLEdBQUcsSUFBSSxHQUFHLEVBQW9DLENBQUM7UUFFOUU7OztXQUdHO1FBQ0ssa0JBQWEsR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFMUM7OztXQUdHO1FBQ0ssMEJBQXFCLEdBQUcsQ0FBQyxDQUFDO1FBRWxDOzs7V0FHRztRQUNL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QyxNQUFNLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2pDLENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsTUFBTSx3QkFBd0I7SUFPNUIsSUFBSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQztJQUNyQyxDQUFDO0lBR0Q7UUFGaUIsb0JBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBR3ZELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxPQUFPLENBQ3hCLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxPQUFPLENBQUM7WUFDaEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUM7UUFDaEMsQ0FBQyxDQUNKLENBQUM7UUFFRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksT0FBTyxDQUN2QixLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3hCLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxDQUFDO1lBQy9CLElBQUksQ0FBQyxjQUFjLEdBQUcsQ0FBQyxNQUFhLEVBQUUsRUFBRTtnQkFDdEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNmLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JDLENBQUMsQ0FBQztRQUNKLENBQUMsQ0FDSixDQUFDO1FBQ0YsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkg