This commit is contained in:
Letter N
2020-07-21 17:47:43 +08:00
parent 9fa060de9e
commit d64c240da3
5 changed files with 154 additions and 12 deletions

View File

@@ -0,0 +1,44 @@
/**
* Ghetto performance measurement tools.
*
* Uses NODE_ENV to redact itself from production bundles.
*
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
*/
let markersByLabel = {};
/**
* Marks a certain spot in the code for later measurements.
*/
const mark = (label, timestamp) => {
if (process.env.NODE_ENV !== 'production') {
markersByLabel[label] = timestamp || Date.now();
}
};
/**
* Calculates and returns the difference between two markers as a string.
*
* Use logger.log() to print the measurement.
*/
const measure = (markerA, markerB) => {
if (process.env.NODE_ENV !== 'production') {
return timeDiff(
markersByLabel[markerA],
markersByLabel[markerB]);
}
};
const timeDiff = (startedAt, finishedAt) => {
const diff = Math.abs(finishedAt - startedAt);
const diffFrames = (diff / 16.6667).toFixed(2);
return `${diff}ms (${diffFrames} frames)`;
};
export const perf = {
mark,
measure,
};

View File

@@ -69,3 +69,31 @@ export const applyMiddleware = (...middlewares) => {
};
};
};
/**
* Combines reducers by running them in their own object namespaces as
* defined in reducersObj paramter.
*
* Main difference from redux/combineReducers is that it preserves keys
* in the state that are not present in the reducers object. This function
* is also more flexible than the redux counterpart.
*/
export const combineReducers = reducersObj => {
const keys = Object.keys(reducersObj);
let hasChanged = false;
return (prevState, action) => {
const nextState = { ...prevState };
for (let key of keys) {
const reducer = reducersObj[key];
const prevDomainState = prevState[key];
const nextDomainState = reducer(prevDomainState, action);
if (prevDomainState !== nextDomainState) {
hasChanged = true;
nextState[key] = nextDomainState;
}
}
return hasChanged
? nextState
: prevState;
};
};

View File

@@ -0,0 +1,76 @@
/**
* Browser-agnostic abstraction of key-value web storage.
*
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
*/
export const STORAGE_NONE = 0;
export const STORAGE_LOCAL_STORAGE = 1;
export const STORAGE_INDEXED_DB = 2;
const createMock = () => {
let storage = {};
const get = key => storage[key];
const set = (key, value) => {
storage[key] = value;
};
const remove = key => {
storage[key] = undefined;
};
const clear = () => {
// NOTE: On IE8, this will probably leak memory if used often.
storage = {};
};
return {
get,
set,
remove,
clear,
engine: STORAGE_NONE,
};
};
const createLocalStorage = () => {
const get = key => {
const value = localStorage.getItem(key);
if (typeof value !== 'string') {
return;
}
return JSON.parse(value);
};
const set = (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
};
const remove = key => {
localStorage.removeItem(key);
};
const clear = () => {
localStorage.clear();
};
return {
get,
set,
remove,
clear,
engine: STORAGE_LOCAL_STORAGE,
};
};
const testLocalStorage = () => {
// Localstorage can sometimes throw an error, even if DOM storage is not
// disabled in IE11 settings.
// See: https://superuser.com/questions/1080011
try {
return Boolean(window.localStorage && window.localStorage.getItem);
}
catch {
return false;
}
};
export const storage = (
testLocalStorage() && createLocalStorage()
|| createMock()
);

View File

@@ -1,4 +1,8 @@
/**
* N-dimensional vector manipulation functions.
*
* Vectors are plain number arrays, i.e. [x, y, z].
*
* @file
* @copyright 2020 Aleksej Komarov
* @license MIT
@@ -6,16 +10,6 @@
import { map, reduce, zipWith } from './collections';
/**
* Creates a vector, with as many dimensions are there are arguments.
*/
export const vecCreate = (...components) => {
if (Array.isArray(components[0])) {
return [...components[0]];
}
return components;
};
const ADD = (a, b) => a + b;
const SUB = (a, b) => a - b;
const MUL = (a, b) => a * b;

View File

@@ -98,8 +98,8 @@ const sendRawMessage = msg => {
socket.send(json);
}
else {
// Keep only 10 latest messages in the queue
if (queue.length > 10) {
// Keep only 100 latest messages in the queue
if (queue.length > 100) {
queue.shift();
}
queue.push(json);