Commit 08ffb11d authored by Jaden DIEFENBAUGH's avatar Jaden DIEFENBAUGH

[js] use "fast-copy" library instead of JSON cloning, #113

parent 1b0b348a
...@@ -5661,6 +5661,11 @@ ...@@ -5661,6 +5661,11 @@
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
"dev": true "dev": true
}, },
"fast-copy": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-1.2.2.tgz",
"integrity": "sha512-qgk7WyVVFNvUzEV/RRQfI7Y6SEjHI+SfmHpkSzzoMUpd4+uXQaeGxhz52/FjnaaNGWxuWXr5l4/kRPD8GPecGA=="
},
"fast-deep-equal": { "fast-deep-equal": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
"bootstrap": "^4.1.3", "bootstrap": "^4.1.3",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"d3": "^5.5.0", "d3": "^5.5.0",
"fast-copy": "^1.2.2",
"fast-levenshtein": "^2.0.6", "fast-levenshtein": "^2.0.6",
"fuse.js": "^3.2.1", "fuse.js": "^3.2.1",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
......
...@@ -11,7 +11,7 @@ import { ...@@ -11,7 +11,7 @@ import {
generateAlgorithmTemplate, generateAlgorithmTemplate,
generateLibraryTemplate, generateLibraryTemplate,
} from '@helpers/api'; } from '@helpers/api';
import { jsonClone } from '@helpers'; import { copyObj } from '@helpers';
import type { BeatEntity, BeatObject } from '@helpers/beat'; import type { BeatEntity, BeatObject } from '@helpers/beat';
import { pluralize } from '@helpers/beat'; import { pluralize } from '@helpers/beat';
...@@ -58,12 +58,12 @@ export default class EntityTemplateGenerationButton extends React.Component<Prop ...@@ -58,12 +58,12 @@ export default class EntityTemplateGenerationButton extends React.Component<Prop
if(!this.props.data.contents.parameters) if(!this.props.data.contents.parameters)
throw new Error(`Bad alg object, no params field: ${ this.props.data.contents }`); throw new Error(`Bad alg object, no params field: ${ this.props.data.contents }`);
const hasParameters = Object.keys(this.props.data.contents.parameters).length > 0; const hasParameters = Object.keys(this.props.data.contents.parameters).length > 0;
uses = jsonClone(this.props.data.contents.uses); uses = copyObj(this.props.data.contents.uses);
res = generateAlgorithmTemplate(this.props.data.name, hasParameters, uses); res = generateAlgorithmTemplate(this.props.data.name, hasParameters, uses);
break; break;
case('library'): case('library'):
// find the used libraries // find the used libraries
uses = jsonClone(this.props.data.contents.uses); uses = copyObj(this.props.data.contents.uses);
res = generateLibraryTemplate(this.props.data.name, uses); res = generateLibraryTemplate(this.props.data.name, uses);
break; break;
default: default:
......
...@@ -17,7 +17,7 @@ import { connect } from 'react-redux'; ...@@ -17,7 +17,7 @@ import { connect } from 'react-redux';
import cn from 'classnames'; import cn from 'classnames';
import { changeObjFieldName, generateNewKey, jsonClone } from '@helpers'; import { changeObjFieldName, generateNewKey, copyObj } from '@helpers';
import { algorithmValidator, BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidAlgorithmObj as getValidObj } from '@helpers/beat'; import { algorithmValidator, BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidAlgorithmObj as getValidObj } from '@helpers/beat';
import type { AlgorithmValidatorObject, BeatObject } from '@helpers/beat'; import type { AlgorithmValidatorObject, BeatObject } from '@helpers/beat';
...@@ -131,7 +131,7 @@ export class AlgorithmEditor extends React.Component<Props, State> { ...@@ -131,7 +131,7 @@ export class AlgorithmEditor extends React.Component<Props, State> {
// updates an old group object to a new group object // updates an old group object to a new group object
updateGroup = (oldGroup: Group, newGroup: Group) => { updateGroup = (oldGroup: Group, newGroup: Group) => {
const gIdx = this.props.data.contents.groups.findIndex(g => JSON.stringify(g) === JSON.stringify(oldGroup)); const gIdx = this.props.data.contents.groups.findIndex(g => JSON.stringify(g) === JSON.stringify(oldGroup));
const newGroups = jsonClone(this.props.data.contents.groups); const newGroups = copyObj(this.props.data.contents.groups);
newGroups[gIdx] = newGroup; newGroups[gIdx] = newGroup;
this.changeContentsVal('groups', newGroups); this.changeContentsVal('groups', newGroups);
} }
...@@ -142,7 +142,7 @@ export class AlgorithmEditor extends React.Component<Props, State> { ...@@ -142,7 +142,7 @@ export class AlgorithmEditor extends React.Component<Props, State> {
// renames a parameter (provide name & value & the old name) // renames a parameter (provide name & value & the old name)
// deletes a parameter (provide null as name, value is optional, the name) // deletes a parameter (provide null as name, value is optional, the name)
updateParameter = (name: null | string, value: any, oldName: ?string) => { updateParameter = (name: null | string, value: any, oldName: ?string) => {
const params = jsonClone(this.props.data.contents.parameters); const params = copyObj(this.props.data.contents.parameters);
if(oldName) if(oldName)
delete params[oldName]; delete params[oldName];
if(name !== null) if(name !== null)
...@@ -159,7 +159,7 @@ export class AlgorithmEditor extends React.Component<Props, State> { ...@@ -159,7 +159,7 @@ export class AlgorithmEditor extends React.Component<Props, State> {
// toggles the algorithm to an analyzer algorithm // toggles the algorithm to an analyzer algorithm
changeToAnalyzer = () => { changeToAnalyzer = () => {
const contents = jsonClone(this.props.data.contents); const contents = copyObj(this.props.data.contents);
contents.groups = contents.groups.map(g => { contents.groups = contents.groups.map(g => {
delete g['outputs']; delete g['outputs'];
return g; return g;
...@@ -177,7 +177,7 @@ export class AlgorithmEditor extends React.Component<Props, State> { ...@@ -177,7 +177,7 @@ export class AlgorithmEditor extends React.Component<Props, State> {
// toggles the algorithm to a normal algorithm // toggles the algorithm to a normal algorithm
changeToNormal = () => { changeToNormal = () => {
const contents = jsonClone(this.props.data.contents); const contents = copyObj(this.props.data.contents);
delete contents.results; delete contents.results;
if(contents.groups.length > 0) if(contents.groups.length > 0)
contents.groups[0].outputs = {}; contents.groups[0].outputs = {};
......
...@@ -29,7 +29,7 @@ import { connect } from 'react-redux'; ...@@ -29,7 +29,7 @@ import { connect } from 'react-redux';
import './DatabaseEditor.css'; import './DatabaseEditor.css';
import { changeObjFieldName, jsonClone } from '@helpers'; import { changeObjFieldName, copyObj } from '@helpers';
import { getValidDatabaseObj as getValidObj } from '@helpers/beat'; import { getValidDatabaseObj as getValidObj } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat'; import type { BeatObject } from '@helpers/beat';
...@@ -209,7 +209,7 @@ export class DatabaseEditor extends React.Component<Props, State> { ...@@ -209,7 +209,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
<Button outline color='secondary' <Button outline color='secondary'
onClick={e => { onClick={e => {
const newSets = [...protocol.sets]; const newSets = [...protocol.sets];
newSets.splice(i + 1, 0, jsonClone(currSet)); newSets.splice(i + 1, 0, copyObj(currSet));
this.updateProtocol( this.updateProtocol(
index, index,
...@@ -591,7 +591,7 @@ export class DatabaseEditor extends React.Component<Props, State> { ...@@ -591,7 +591,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
protocols.splice( protocols.splice(
protocolIdx + 1, protocolIdx + 1,
0, 0,
jsonClone(protocol) copyObj(protocol)
); );
this.setContents({ this.setContents({
...@@ -675,7 +675,7 @@ export class DatabaseEditor extends React.Component<Props, State> { ...@@ -675,7 +675,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
<Button size='sm' outline color='secondary' <Button size='sm' outline color='secondary'
onClick={e => { onClick={e => {
const newSets = [...p.sets]; const newSets = [...p.sets];
newSets.splice(j + 1, 0, jsonClone(s)); newSets.splice(j + 1, 0, copyObj(s));
this.updateProtocol( this.updateProtocol(
i, i,
...@@ -755,7 +755,7 @@ export class DatabaseEditor extends React.Component<Props, State> { ...@@ -755,7 +755,7 @@ export class DatabaseEditor extends React.Component<Props, State> {
protocols.splice( protocols.splice(
protocolIdx + 1, protocolIdx + 1,
0, 0,
jsonClone(protocol) copyObj(protocol)
); );
this.setContents({ this.setContents({
......
...@@ -37,7 +37,7 @@ import type { ...@@ -37,7 +37,7 @@ import type {
BeatObject, BeatObject,
} from '@helpers/beat.js'; } from '@helpers/beat.js';
import { changeObjFieldName, generateNewKey, jsonClone } from '@helpers'; import { changeObjFieldName, generateNewKey, copyObj } from '@helpers';
type Props = { type Props = {
data: BeatObject, data: BeatObject,
......
...@@ -31,7 +31,7 @@ import lev from 'fast-levenshtein'; ...@@ -31,7 +31,7 @@ import lev from 'fast-levenshtein';
import './ExperimentEditor.css'; import './ExperimentEditor.css';
import { getValidExperimentObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat'; import { getValidExperimentObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat';
import type { BeatObject, ParameterValue, BeatEnvironment } from '@helpers/beat'; import type { BeatObject, ParameterValue, BeatEnvironment } from '@helpers/beat';
import { changeObjFieldName, sortObject, jsonClone } from '@helpers'; import { changeObjFieldName, sortObject, copyObj } from '@helpers';
import * as Selectors from '@store/selectors.js'; import * as Selectors from '@store/selectors.js';
import * as Actions from '@store/actions.js'; import * as Actions from '@store/actions.js';
...@@ -800,7 +800,7 @@ export class ExperimentEditor extends React.Component<Props, State> { ...@@ -800,7 +800,7 @@ export class ExperimentEditor extends React.Component<Props, State> {
queue: queue, queue: queue,
}); });
else { else {
const newBlock = jsonClone(block); const newBlock = copyObj(block);
delete newBlock.environment; delete newBlock.environment;
delete newBlock.queue; delete newBlock.queue;
updateBlock(newBlock); updateBlock(newBlock);
......
...@@ -25,7 +25,7 @@ import { connect } from 'react-redux'; ...@@ -25,7 +25,7 @@ import { connect } from 'react-redux';
import { getValidLibraryObj as getValidObj } from '@helpers/beat'; import { getValidLibraryObj as getValidObj } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat'; import type { BeatObject } from '@helpers/beat';
import { changeObjFieldName, jsonClone } from '@helpers'; import { changeObjFieldName, copyObj } from '@helpers';
import * as Selectors from '@store/selectors.js'; import * as Selectors from '@store/selectors.js';
import { debounce } from 'throttle-debounce'; import { debounce } from 'throttle-debounce';
......
...@@ -17,7 +17,7 @@ import { connect } from 'react-redux'; ...@@ -17,7 +17,7 @@ import { connect } from 'react-redux';
import cn from 'classnames'; import cn from 'classnames';
import { changeObjFieldName, generateNewKey, jsonClone } from '@helpers'; import { changeObjFieldName, generateNewKey, copyObj } from '@helpers';
import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterObj as getValidObj } from '@helpers/beat'; import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterObj as getValidObj } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat'; import type { BeatObject } from '@helpers/beat';
...@@ -78,7 +78,7 @@ export class PlotterEditor extends React.Component<Props, State> { ...@@ -78,7 +78,7 @@ export class PlotterEditor extends React.Component<Props, State> {
// renames a parameter (provide name & value & the old name) // renames a parameter (provide name & value & the old name)
// deletes a parameter (provide null as name, value is optional, the name) // deletes a parameter (provide null as name, value is optional, the name)
updateParameter = (name: null | string, value: any, oldName: ?string) => { updateParameter = (name: null | string, value: any, oldName: ?string) => {
const params = jsonClone(this.props.data.contents.parameters); const params = copyObj(this.props.data.contents.parameters);
if(oldName) if(oldName)
delete params[oldName]; delete params[oldName];
if(name !== null) if(name !== null)
......
...@@ -17,7 +17,7 @@ import { connect } from 'react-redux'; ...@@ -17,7 +17,7 @@ import { connect } from 'react-redux';
import cn from 'classnames'; import cn from 'classnames';
import { changeObjFieldName, generateNewKey, jsonClone } from '@helpers'; import { changeObjFieldName, generateNewKey, copyObj } from '@helpers';
import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterparameterObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat'; import { BUILTIN_TYPES, ANALYZER_RESULT_TYPES, getValidPlotterparameterObj as getValidObj, expGetDefaultParameterValue as getDefaultParameterValue } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat'; import type { BeatObject } from '@helpers/beat';
......
...@@ -29,7 +29,7 @@ import { ...@@ -29,7 +29,7 @@ import {
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { ContextMenu, MenuItem, ContextMenuTrigger, SubMenu } from 'react-contextmenu'; import { ContextMenu, MenuItem, ContextMenuTrigger, SubMenu } from 'react-contextmenu';
import { getRandomBrightColor, generateNewKey, jsonClone } from '@helpers'; import { getRandomBrightColor, generateNewKey, copyObj } from '@helpers';
import { getValidToolchainObj as getValidObj } from '@helpers/beat'; import { getValidToolchainObj as getValidObj } from '@helpers/beat';
import type { BeatObject } from '@helpers/beat'; import type { BeatObject } from '@helpers/beat';
import { fetchLayout, genModuleApiFuncs } from '@helpers/api'; import { fetchLayout, genModuleApiFuncs } from '@helpers/api';
...@@ -105,7 +105,7 @@ const generateNewHistory = (state: State, data: any): History => { ...@@ -105,7 +105,7 @@ const generateNewHistory = (state: State, data: any): History => {
return { return {
past: [ past: [
...state.history.past, ...state.history.past,
jsonClone(data), copyObj(data),
], ],
future: [], future: [],
}; };
...@@ -182,7 +182,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> { ...@@ -182,7 +182,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> {
const newPast = [...this.state.history.past]; const newPast = [...this.state.history.past];
const newData = newPast.pop(); const newData = newPast.pop();
const newFuture = [...this.state.history.future, jsonClone(this.props.data)]; const newFuture = [...this.state.history.future, copyObj(this.props.data)];
this.setState({ this.setState({
history: { history: {
past: newPast, past: newPast,
...@@ -207,7 +207,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> { ...@@ -207,7 +207,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> {
const newFuture = [...this.state.history.future]; const newFuture = [...this.state.history.future];
const newData = newFuture.pop(); const newData = newFuture.pop();
const newPast = [...this.state.history.past, jsonClone(this.props.data)]; const newPast = [...this.state.history.past, copyObj(this.props.data)];
this.setState({ this.setState({
history: { history: {
past: newPast, past: newPast,
...@@ -583,7 +583,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> { ...@@ -583,7 +583,7 @@ export class ToolchainEditor extends React.PureComponent<Props, State> {
// as well as any connections to/from it // as well as any connections to/from it
// if it was the sole member of a group, deletes the group too // if it was the sole member of a group, deletes the group too
deleteBlocks = (names: string[]) => { deleteBlocks = (names: string[]) => {
const rep = jsonClone(this.props.data.contents.representation); const rep = copyObj(this.props.data.contents.representation);
names.forEach(name => { names.forEach(name => {
delete rep.blocks[name]; delete rep.blocks[name];
......
// @flow // @flow
// BEAT-specific helpers // BEAT-specific helpers
import { jsonClone } from '.'; import { copyObj } from '.';
// all the BEAT entities // all the BEAT entities
export type BeatEntity = 'database' | 'library' | 'dataformat' | 'algorithm' | 'toolchain' | 'experiment' | 'plotter' | 'plotterparameter'; export type BeatEntity = 'database' | 'library' | 'dataformat' | 'algorithm' | 'toolchain' | 'experiment' | 'plotter' | 'plotterparameter';
...@@ -258,7 +258,7 @@ export const getValidAlgorithmObj = (data: BeatObject = {name: '', contents: {}} ...@@ -258,7 +258,7 @@ export const getValidAlgorithmObj = (data: BeatObject = {name: '', contents: {}}
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
...@@ -284,7 +284,7 @@ export const getValidDatabaseObj = (data: BeatObject = {name: '', contents: {}}) ...@@ -284,7 +284,7 @@ export const getValidDatabaseObj = (data: BeatObject = {name: '', contents: {}})
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
if(Array.isArray(getObj.contents.protocols)){ if(Array.isArray(getObj.contents.protocols)){
...@@ -312,7 +312,7 @@ export const getValidDataformatObj = (data: BeatObject = {name: '', contents: {} ...@@ -312,7 +312,7 @@ export const getValidDataformatObj = (data: BeatObject = {name: '', contents: {}
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
...@@ -353,7 +353,7 @@ export const getValidExperimentObj = (data: BeatObject = {name: '', contents: {} ...@@ -353,7 +353,7 @@ export const getValidExperimentObj = (data: BeatObject = {name: '', contents: {}
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
getObj.contents.datasets = getObj.contents.datasets || {}; getObj.contents.datasets = getObj.contents.datasets || {};
...@@ -428,7 +428,7 @@ export const getValidLibraryObj = (data: BeatObject = {name: '', contents: {}}) ...@@ -428,7 +428,7 @@ export const getValidLibraryObj = (data: BeatObject = {name: '', contents: {}})
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
...@@ -449,7 +449,7 @@ export const getValidToolchainObj = (data: BeatObject = {name: '', contents: {}} ...@@ -449,7 +449,7 @@ export const getValidToolchainObj = (data: BeatObject = {name: '', contents: {}}
name: '', name: '',
contents: {}, contents: {},
extraContents: {}, extraContents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
...@@ -480,7 +480,7 @@ export const getValidPlotterObj = (data: BeatObject = {name: '', contents: {}}) ...@@ -480,7 +480,7 @@ export const getValidPlotterObj = (data: BeatObject = {name: '', contents: {}})
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
...@@ -502,7 +502,7 @@ export const getValidPlotterparameterObj = (data: BeatObject = {name: '', conten ...@@ -502,7 +502,7 @@ export const getValidPlotterparameterObj = (data: BeatObject = {name: '', conten
const getObj = { const getObj = {
name: '', name: '',
contents: {}, contents: {},
...jsonClone(data) ...copyObj(data)
}; };
const obj = { const obj = {
......
// @flow // @flow
// basic helpers - common bits of code refactored to DRY // basic helpers - common bits of code refactored to DRY
import copy from 'fast-copy';
// changes a field in an object to a different name // changes a field in an object to a different name
// only required because keys are often mutable // only required because keys are often mutable
...@@ -48,9 +49,8 @@ export const sortObject = (o: any) => Object.entries(o) ...@@ -48,9 +49,8 @@ export const sortObject = (o: any) => Object.entries(o)
.sort(([n1, v1], [n2, v2]) => n1 > n2 ? 1 : -1) .sort(([n1, v1], [n2, v2]) => n1 > n2 ? 1 : -1)
.reduce((o, [n, v]) => ({...o, [n]: Object((v: any)) === v ? sortObject(v) : v}), {}); .reduce((o, [n, v]) => ({...o, [n]: Object((v: any)) === v ? sortObject(v) : v}), {});
// clones a JSON obj via stringify/parse export const copyObj = (any: any) => {
export const jsonClone = (any: any) => { return copy(any);
return JSON.parse(JSON.stringify(any));
}; };
export type GenericObject = {[string]: any}; export type GenericObject = {[string]: any};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment