Skip to content

Commit

Permalink
#57 remove runtime type checks with typeof/instanceof
Browse files Browse the repository at this point in the history
  • Loading branch information
artin-phares committed Nov 29, 2017
1 parent f36b66e commit af4d44b
Show file tree
Hide file tree
Showing 32 changed files with 86 additions and 137 deletions.
5 changes: 3 additions & 2 deletions src/action/handlers/create-idea.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import required from 'utils/required-params';
import Patch from 'utils/state/Patch';

import isValidPathWeight from 'utils/graph/is-valid-path-weight';

import getIdea from 'action/utils/get-idea';
import weighAssociation from 'model/utils/weigh-association';

Expand Down Expand Up @@ -62,8 +64,7 @@ export default function createIdea(state, data) {
idea.edgesToChilds = [];

// ensure parent idea RPW is valid
if (parent.rootPathWeight === undefined ||
!Number.isFinite(parent.rootPathWeight)) {
if (!isValidPathWeight(parent.rootPathWeight)) {
throw Error(
`Idea '${parent.id}' has invalid root path weight ` +
`'${parent.rootPathWeight}'`);
Expand Down
15 changes: 5 additions & 10 deletions src/data/db/ideas.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import assert from 'utils/assert';

import Idea from 'model/entities/Idea';
import IdeaType from 'model/entities/Idea';

import toModel from 'data/mappers/dbo-to-idea';
import toDbo from 'data/mappers/idea-to-dbo';
Expand All @@ -11,7 +9,7 @@ import isEmptyDbo from 'data/utils/is-empty-dbo';
* Gets idea
* @param {PouchDB.Database} db
* @param {string} ideaId
* @return {Promise.<Idea>}
* @return {Promise.<IdeaType>}
*/
export async function get(db, ideaId) {
const dbo = await db.get(ideaId);
Expand All @@ -21,7 +19,7 @@ export async function get(db, ideaId) {
/**
* Gets all ideas
* @param {PouchDB.Database} db
* @return {Promise.<Array.<Idea>>}
* @return {Promise.<Array.<IdeaType>>}
*/
export async function getAll(db) {

Expand All @@ -37,20 +35,17 @@ export async function getAll(db) {
/**
* Adds new idea
* @param {PouchDB.Database} db
* @param {Idea} idea
* @param {IdeaType} idea
*/
export async function add(db, idea) {
assert(idea instanceof Idea,
'Argument should be instance of Idea');

const dbo = toDbo(idea);
await db.put(dbo);
}

/**
* Updates idea
* @param {PouchDB.Database} db
* @param {Idea|object} model - model or patch
* @param {IdeaType|object} model - model or patch
*/
export async function update(db, model) {
const dbo = toDbo(model);
Expand Down
10 changes: 10 additions & 0 deletions src/model/utils/is-valid-scale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Checks whether scale is valid
*
* @param {number} scale - graph viewbox or node scale
* @return {boolean}
*/
export default function isValidScale(scale) {

return scale !== undefined && scale > 0;
}
25 changes: 3 additions & 22 deletions src/utils/PriorityQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ export default class PriorityQueue {

/**
* Adds new item with corresponding priority.
* @param {object} item
* @param {Object.<string, *>} item - item to enqueue. objects allowed only.
* primitives will not work since each item should be unique
* to be able to update their priority properly
* @param {number} priority
*/
addWithPriority(item, priority) {
validateParams(item, priority);

// get entry position (time - O(log n))
const idx = binarySearchIndex(this._entries, priority);
Expand All @@ -42,7 +43,6 @@ export default class PriorityQueue {
* @param {number} priority
*/
updatePriority(item, priority) {
validateParams(item, priority);

// find entry by item value (time - O(n))
const idx = this._entries.findIndex(e => e.item === item);
Expand Down Expand Up @@ -95,25 +95,6 @@ export default class PriorityQueue {
}
}

/**
* Validates params
* @param {object} item
* @param {number} priority
*/
function validateParams(item, priority) {

// allow object items only.
// primitives will not work since each item should be unique
// to be able to update item priority properly
if (typeof item !== 'object' || item === null) {
throw Error(`Invalid item '${item}' received. Object expected.`);
}

if (!Number.isFinite(priority)) {
throw Error(`Invalid priority '${priority}' received`);
}
}

/**
* Find position for new item in array to keep it sorted
*
Expand Down
3 changes: 0 additions & 3 deletions src/utils/get-map-values.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import assert from 'utils/assert';

/**
* Gets values of Map object
*
Expand All @@ -11,6 +9,5 @@ import assert from 'utils/assert';
* @return {array} values
*/
export default function getMapValues(map) {
assert(map instanceof Map, `Invalid map object '${map}'`);
return [...map.values()];
}
3 changes: 2 additions & 1 deletion src/utils/graph/build-graph-from-matrix.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import required from 'utils/required-params';
import isValidPathWeight from 'utils/graph//is-valid-path-weight';

const charCodeA = 65;
const charCount = 26;
Expand Down Expand Up @@ -49,7 +50,7 @@ export default function buildGraphFromMatrix(opts) {
.filter(s => s !== '')
.map(edgeWeightStr => {
const edgeWeight = Number(edgeWeightStr);
if (!Number.isFinite(edgeWeight) || edgeWeight < 0) {
if (!isValidPathWeight(edgeWeight)) {
throw Error(
`Invalid outgoing edge weight '${edgeWeightStr}' ` +
`for vertex '${headId}'`);
Expand Down
3 changes: 2 additions & 1 deletion src/utils/graph/calc-root-paths.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import required from 'utils/required-params';
import PriorityQueue from 'utils/PriorityQueue';
import isValidPathWeight from 'utils/graph/is-valid-path-weight';

/**
* Calculates minimal root paths (MRP) for each vertex in the graph.
Expand Down Expand Up @@ -83,7 +84,7 @@ export default function calcRootPaths(opts) {
const edgeWeight = getEdgeWeight(edge, replaceEdgeWeights);

// ensure edge weight is valid
if (!Number.isFinite(edgeWeight) || edgeWeight < 0) {
if (!isValidPathWeight(edgeWeight)) {
throw Error(
`Edge '${edge.id}' has invalid weight '${edgeWeight}'`);
}
Expand Down
12 changes: 12 additions & 0 deletions src/utils/graph/is-valid-path-weight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Checks whether path weight is valid
*
* @param {number} pathWeight - association weight or node root path weight
* @return {boolean}
*/
export default function isValidPathWeight(pathWeight) {

return pathWeight !== undefined &&
Number.isFinite(pathWeight) &&
pathWeight >= 0;
}
4 changes: 2 additions & 2 deletions src/utils/graph/map-graph.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import required from 'utils/required-params';
import WeightZone from 'utils/graph/WeightZone';
import isValidPathWeight from 'utils/graph/is-valid-path-weight';

import IdeaType from 'model/entities/Idea';
import NodeType from 'vm/map/entities/Node';
Expand Down Expand Up @@ -214,8 +215,7 @@ function getWeightZoneForVertex(vertex, focusZoneMax, shadeZoneAmount) {
const {rootPathWeight} = vertex;

// ensure root path weight set
if (rootPathWeight === undefined || !Number.isFinite(rootPathWeight) ||
rootPathWeight < 0) {
if (!isValidPathWeight(rootPathWeight)) {
throw Error(`Invalid root path weight '${rootPathWeight}'`);
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/guard-object-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
export default function guardObjectProps(object) {

if (object == null || typeof object !== 'object') {
if (!object) {
throw Error(`Invalid object received '${object}'`);
}

Expand Down
2 changes: 0 additions & 2 deletions src/utils/init-instance.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import assert from 'utils/assert';
import initProps from 'utils/init-props';
import guardObjectProps from 'utils/guard-object-props';

Expand All @@ -17,7 +16,6 @@ import guardObjectProps from 'utils/guard-object-props';
* @return {object} instance
*/
export default function initInstance(instance, propsObj) {
assert(typeof instance === 'object', `Invalid instance '${instance}'`);

const guardedInstance = guardObjectProps(instance);
initProps(guardedInstance, propsObj);
Expand Down
5 changes: 1 addition & 4 deletions src/utils/init-props.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import assert from 'utils/assert';
import updateObject from 'utils/update-object';

/**
Expand All @@ -19,14 +18,12 @@ import updateObject from 'utils/update-object';
* @param {object} [propsObj]
*/
export default function initProps(instance, propsObj) {

if (propsObj === undefined) {
// props not received
return;
}

assert(typeof instance === 'object', `Invalid instance '${instance}'`);
assert(typeof propsObj === 'object', `Invalid props object '${propsObj}'`);

try {
updateObject(instance, propsObj);
} catch (e) {
Expand Down
6 changes: 1 addition & 5 deletions src/utils/perf.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
* perf.endGroup(groupId)
*
*/
import assert from 'utils/assert';

import guid from 'utils/guid';

const groups = new Map();
Expand Down Expand Up @@ -95,7 +93,6 @@ function getGroupId() {
* @return {string} groupId
*/
function startGroup(label) {
assert(label, `Invalid group label '${label}'`);

const groupId = getGroupId();

Expand Down Expand Up @@ -138,8 +135,7 @@ export function endGroup(groupId, labelSuffix) {
* @return {string} measure Id
*/
function start(label, groupId) {
assert(label, `Invalid measure label '${label}'`);


const perfId = guid();
performance.mark(perfId);

Expand Down
1 change: 1 addition & 0 deletions src/utils/reg-mutators-folder.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function regMutatorsFolder(context) {
context.keys().forEach(modulePath => {
const module = context(modulePath);
const type = modulePath.match(/.+\/(.+)\./i)[1];

if (mutators[type]) {
throw Error(`Mutation '${type}' already has registered handler`);
}
Expand Down
2 changes: 2 additions & 0 deletions src/utils/required-params.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
* const {optionalParam} = params;
* }
*
* TODO: try typedef generic function function(T): T
*
* @param {object} params
* @return {object}
*/
Expand Down
6 changes: 2 additions & 4 deletions src/utils/state/Handler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import assert from 'utils/assert';
import required from 'utils/required-params';
import Patch from './Patch';

Expand Down Expand Up @@ -75,6 +74,7 @@ export default class Handler {
}

const validatedMutate = patch => {
// TODO: replace with static type checks. create handler func type.
if (!(patch instanceof Patch)) {
throw Error(
`Action handler should pass instance of a Patch ` +
Expand All @@ -92,6 +92,7 @@ export default class Handler {
);

const handleResult = patch => {
// TODO: replace with static type checks. create handler func type.
if (patch !== undefined && !(patch instanceof Patch)) {
throw Error(
`Action handler should return undefined or ` +
Expand Down Expand Up @@ -120,9 +121,6 @@ export default class Handler {
// @ts-ignore
handlers = handlers.reduce((res, a) => res.concat(a), []);

assert(handlers.every(g => g instanceof Handler),
'Each argument should be instance of Handler');

const handler = new Handler();

handlers
Expand Down
4 changes: 0 additions & 4 deletions src/utils/state/Patch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import assert from 'utils/assert';
import dedup from 'utils/dedup-array';

import Mutation from './Mutation';
Expand Down Expand Up @@ -138,9 +137,6 @@ export default class Patch {

patches = patches.filter(p => p !== undefined);

assert(patches.every(p => p instanceof Patch),
'Each argument should be instance of Patch');

const mutations = patches.reduce(
(comb, patch) => ([...comb, ...patch]), []);

Expand Down
5 changes: 3 additions & 2 deletions src/utils/state/Store.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// @ts-ignore
import EventEmitter from 'events';

import guid from 'utils/guid';
import HandlerType from './Handler';

import Action from './Action';

import PatchType from './Patch';

/**
* Application state container.
*
Expand Down Expand Up @@ -69,7 +70,7 @@ export default class Store {

/**
* List of middlewares
* @type {Array.<function>}
* @type {Array.<object>}
*/
_middlewares = [];

Expand Down
10 changes: 3 additions & 7 deletions src/utils/state/middlewares/logger/log.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import assert from 'utils/assert';
import LogEntry from './LogEntry';
import LogEntryType from './LogEntry';

// console style tag
const S = '%c';
Expand All @@ -26,13 +25,10 @@ const font = {

/**
* Logs store action to console
* @param {LogEntry} entry
* @param {LogEntryType} entry
*/
export default function(entry) {

assert(entry instanceof LogEntry,
'Argument should be instance of LogEntry');

// group header
console.groupCollapsed(...getHeader(entry));

Expand Down Expand Up @@ -81,7 +77,7 @@ export default function(entry) {

/**
* Composes header string
* @param {LogEntry} entry
* @param {LogEntryType} entry
* @return {Array.<string>} header + styles
*/
function getHeader(entry) {
Expand Down
Loading

0 comments on commit af4d44b

Please sign in to comment.