Skip to content

Commit

Permalink
fix(params): Clone all properties of a Node. Introduce applyRawParams()
Browse files Browse the repository at this point in the history
  • Loading branch information
christopherthielen committed Mar 26, 2016
1 parent f5fd578 commit 88c624d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 14 deletions.
3 changes: 2 additions & 1 deletion src/common/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,10 @@ export function find(collection, callback) {
return result;
}

/** Given an object, returns a new object, where each property is transformed by the callback function */
export let mapObj: <T,U>(collection: { [key: string]: T }, callback: Mapper<T,U>) => { [key: string]: U } = map;
/** Given an array, returns a new array, where each element is transformed by the callback function */
export function map<T, U>(collection: T[], callback: Mapper<T, U>): U[];
/** Given an object, returns a new object, where each property is transformed by the callback function */
export function map<T, U>(collection: { [key: string]: T }, callback: Mapper<T, U>): { [key: string]: U }
/** Maps an array or object properties using a callback function */
export function map(collection: any, callback: any): any {
Expand Down
34 changes: 25 additions & 9 deletions src/path/node.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @module path */ /** for typedoc */
import {extend, applyPairs, map, find, allTrueR, values} from "../common/common";
import {extend, applyPairs, map, find, allTrueR, values, mapObj} from "../common/common";
import {prop, propEq} from "../common/hof";
import {State} from "../state/module";
import {RawParams} from "../params/interface";
Expand All @@ -9,22 +9,38 @@ import {ViewConfig} from "../view/interface";
import {Resolvables} from "../resolve/interface";

export class Node {
public state: State;
public paramSchema: Param[];
public paramValues: { [key: string]: any };
public resolves: Resolvables;
public views: ViewConfig[];
public resolveContext: ResolveContext;
public resolveInjector: ResolveInjector;

// Possibly extract this logic into an intermediary object that maps states to nodes
constructor(public state: State, params: RawParams = {}, resolvables: Resolvables = {}) {
// Object.freeze(extend(this, { ... }))
this.paramSchema = state.parameters({ inherit: false });
constructor(state: Node);
constructor(state: State);
constructor(state) {
if (state instanceof Node) {
let node: Node = state;
this.state = node.state;
this.paramSchema = node.paramSchema.slice();
this.paramValues = extend({}, node.paramValues);
this.resolves = extend({}, node.resolves);
this.views = node.views && node.views.slice();
this.resolveContext = node.resolveContext;
this.resolveInjector = node.resolveInjector;
} else {
this.state = state;
this.paramSchema = state.parameters({ inherit: false });
this.paramValues = {};
this.resolves = mapObj(state.resolve, (fn: Function, name: string) => new Resolvable(name, fn));
}
}

applyRawParams(params: RawParams): Node {
const getParamVal = (paramDef: Param) => [ paramDef.id, paramDef.value(params[paramDef.id]) ];
this.paramValues = this.paramSchema.reduce((memo, pDef) => applyPairs(memo, getParamVal(pDef)), {});

this.resolves = extend(map(state.resolve, (fn: Function, name: string) => new Resolvable(name, fn)), resolvables);
return this;
}

parameter(name: string): Param {
Expand All @@ -36,8 +52,8 @@ export class Node {
return this.state === node.state && keys.map(paramValsEq).reduce(allTrueR, true);
}

static clone(node: Node, update: any = {}) {
return new Node(node.state, (update.paramValues || node.paramValues), (update.resolves || node.resolves));
static clone(node: Node) {
return new Node(node);
}

/**
Expand Down
8 changes: 5 additions & 3 deletions src/path/pathFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class PathFactory {
/** Given a fromPath: Node[] and a TargetState, builds a toPath: Node[] */
static buildToPath(fromPath: Node[], targetState: TargetState): Node[] {
let toParams = targetState.params();
let toPath: Node[] = targetState.$state().path.map(state => new Node(state, toParams));
let toPath: Node[] = targetState.$state().path.map(state => new Node(state).applyRawParams(toParams));

if (targetState.options().inherit) toPath = PathFactory.inheritParams(fromPath, toPath, Object.keys(toParams));
return toPath;
Expand Down Expand Up @@ -70,7 +70,7 @@ export class PathFactory {
let fromParamVals = nodeParamVals(_fromPath, toNode.state) || {};
// extend toParamVals with any fromParamVals, then override any of those those with incomingParamVals
let ownParamVals: RawParams = extend(toParamVals, fromParamVals, incomingParamVals);
return new Node(toNode.state, ownParamVals);
return new Node(toNode.state).applyRawParams(ownParamVals);
});

// The param keys specified by the incoming toParams
Expand Down Expand Up @@ -111,7 +111,9 @@ export class PathFactory {

/** Given a retained node, return a new node which uses the to node's param values */
function applyToParams(retainedNode: Node, idx: number): Node {
return Node.clone(retainedNode, { paramValues: toPath[idx].paramValues });
let cloned = Node.clone(retainedNode);
cloned.paramValues = toPath[idx].paramValues;
return cloned;
}

let from: Node[], retained: Node[], exiting: Node[], entering: Node[], to: Node[];
Expand Down
2 changes: 1 addition & 1 deletion src/state/stateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export class StateService {

let ref: TargetState = this.target(to, toParams, options);
let latestTreeChanges: TreeChanges = treeChangesQueue.peekTail();
const rootPath = () => PathFactory.bindTransNodesToPath([new Node(this.stateRegistry.root(), {})]);
const rootPath = () => PathFactory.bindTransNodesToPath([new Node(this.stateRegistry.root())]);
let currentPath: Node[] = latestTreeChanges ? latestTreeChanges.to : rootPath();

if (!ref.exists())
Expand Down

0 comments on commit 88c624d

Please sign in to comment.