feat(router): hash-cons ComponentInstructions
This commit is contained in:
parent
76e1f863a2
commit
e1a7e0329c
|
@ -83,6 +83,12 @@ function stringifyAux(instruction: Instruction): string {
|
|||
*
|
||||
* `ComponentInstructions` is a public API. Instances of `ComponentInstruction` are passed
|
||||
* to route lifecycle hooks, like {@link CanActivate}.
|
||||
*
|
||||
* `ComponentInstruction`s are [https://en.wikipedia.org/wiki/Hash_consing](hash consed). You should
|
||||
* never construct one yourself with "new." Instead, rely on {@link PathRecognizer} to construct
|
||||
* `ComponentInstruction`s.
|
||||
*
|
||||
* You should not modify this object. It should be treated as immutable.
|
||||
*/
|
||||
export class ComponentInstruction {
|
||||
reuse: boolean = false;
|
||||
|
|
|
@ -192,6 +192,8 @@ export class PathRecognizer {
|
|||
specificity: number;
|
||||
terminal: boolean = true;
|
||||
hash: string;
|
||||
private cache: Map<string, ComponentInstruction> = new Map<string, ComponentInstruction>();
|
||||
|
||||
|
||||
// TODO: cache component instruction instances by params and by ParsedUrl instance
|
||||
|
||||
|
@ -252,23 +254,26 @@ export class PathRecognizer {
|
|||
|
||||
var auxiliary;
|
||||
var instruction: ComponentInstruction;
|
||||
var urlParams;
|
||||
var allParams;
|
||||
if (isPresent(currentSegment)) {
|
||||
// If this is the root component, read query params. Otherwise, read matrix params.
|
||||
var paramsSegment = beginningSegment instanceof RootUrl ? beginningSegment : currentSegment;
|
||||
|
||||
var allParams = isPresent(paramsSegment.params) ?
|
||||
StringMapWrapper.merge(paramsSegment.params, positionalParams) :
|
||||
positionalParams;
|
||||
allParams = isPresent(paramsSegment.params) ?
|
||||
StringMapWrapper.merge(paramsSegment.params, positionalParams) :
|
||||
positionalParams;
|
||||
|
||||
var urlParams = serializeParams(paramsSegment.params);
|
||||
urlParams = serializeParams(paramsSegment.params);
|
||||
|
||||
instruction = new ComponentInstruction(urlPath, urlParams, this, allParams);
|
||||
|
||||
auxiliary = currentSegment.auxiliary;
|
||||
} else {
|
||||
instruction = new ComponentInstruction(urlPath, [], this, positionalParams);
|
||||
allParams = positionalParams;
|
||||
auxiliary = [];
|
||||
urlParams = [];
|
||||
}
|
||||
instruction = this._getInstruction(urlPath, urlParams, this, allParams);
|
||||
return new PathMatch(instruction, nextSegment, auxiliary);
|
||||
}
|
||||
|
||||
|
@ -289,6 +294,18 @@ export class PathRecognizer {
|
|||
var nonPositionalParams = paramTokens.getUnused();
|
||||
var urlParams = serializeParams(nonPositionalParams);
|
||||
|
||||
return new ComponentInstruction(urlPath, urlParams, this, params);
|
||||
return this._getInstruction(urlPath, urlParams, this, params);
|
||||
}
|
||||
|
||||
private _getInstruction(urlPath: string, urlParams: List<string>, _recognizer: PathRecognizer,
|
||||
params: StringMap<string, any>): ComponentInstruction {
|
||||
var hashKey = urlPath + '?' + urlParams.join('?');
|
||||
if (this.cache.has(hashKey)) {
|
||||
return this.cache.get(hashKey);
|
||||
}
|
||||
var instruction = new ComponentInstruction(urlPath, urlParams, _recognizer, params);
|
||||
this.cache.set(hashKey, instruction);
|
||||
|
||||
return instruction;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,17 @@ export function main() {
|
|||
.toThrowError(`Path "hi//there" contains "//" which is not allowed in a route config.`);
|
||||
});
|
||||
|
||||
it('should return the same instruction instance when recognizing the same path', () => {
|
||||
var rec = new PathRecognizer('/one', mockRouteHandler);
|
||||
|
||||
var one = new Url('one', null, null, {});
|
||||
|
||||
var firstMatch = rec.recognize(one);
|
||||
var secondMatch = rec.recognize(one);
|
||||
|
||||
expect(firstMatch.instruction).toBe(secondMatch.instruction);
|
||||
});
|
||||
|
||||
describe('querystring params', () => {
|
||||
it('should parse querystring params so long as the recognizer is a root', () => {
|
||||
var rec = new PathRecognizer('/hello/there', mockRouteHandler);
|
||||
|
|
Loading…
Reference in New Issue