Skip to content

Commit 3703b31

Browse files
authored
fix: partial revert of PR #1516 custom deepCopy() for array in SF/LWC (#2056)
1 parent e23f52d commit 3703b31

File tree

6 files changed

+55
-26
lines changed

6 files changed

+55
-26
lines changed

frameworks/slickgrid-react/src/components/slickgrid-react.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
5050
import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component';
5151
import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
5252
import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component';
53-
import { extend } from '@slickgrid-universal/utils';
53+
import { deepCopy, extend } from '@slickgrid-universal/utils';
5454
import { dequal } from 'dequal/lite';
5555
import React from 'react';
5656
import type { Subscription } from 'rxjs';
@@ -189,7 +189,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
189189
const prevDatasetLn = this._currentDatasetLength;
190190
const isDatasetEqual = dequal(newDataset, this.dataset || []);
191191
const isDeepCopyDataOnPageLoadEnabled = !!this._options?.enableDeepCopyDatasetOnPageLoad;
192-
let data = isDeepCopyDataOnPageLoadEnabled ? extend(true, [], newDataset) : newDataset;
192+
let data = isDeepCopyDataOnPageLoadEnabled ? deepCopy(newDataset) : newDataset;
193193

194194
// when Tree Data is enabled and we don't yet have the hierarchical dataset filled, we can force a convert+sort of the array
195195
if (

frameworks/slickgrid-vue/src/components/SlickgridVue.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-compone
4747
import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
4848
import { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
4949
import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component';
50-
import { extend } from '@slickgrid-universal/utils';
50+
import { deepCopy, extend } from '@slickgrid-universal/utils';
5151
import { dequal } from 'dequal/lite';
5252
import {
5353
type ComponentPublicInstance,
@@ -214,7 +214,7 @@ watch(
214214
const prevDatasetLn = currentDatasetLength;
215215
const isDatasetEqual = dequal(newDataset, dataModel.value || []);
216216
const isDeepCopyDataOnPageLoadEnabled = !!_gridOptions.value?.enableDeepCopyDatasetOnPageLoad;
217-
let data = isDeepCopyDataOnPageLoadEnabled ? extend(true, [], newDataset) : newDataset;
217+
let data = isDeepCopyDataOnPageLoadEnabled ? deepCopy(newDataset) : newDataset;
218218
219219
// when Tree Data is enabled and we don't yet have the hierarchical dataset filled, we can force a convert+sort of the array
220220
if (

packages/common/src/services/filter.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type BasePubSubService } from '@slickgrid-universal/event-pub-sub';
2-
import { extend, queueMicrotaskOrSetTimeout, stripTags } from '@slickgrid-universal/utils';
2+
import { deepCopy, extend, queueMicrotaskOrSetTimeout, stripTags } from '@slickgrid-universal/utils';
33
import { dequal } from 'dequal/lite';
44

55
import { Constants } from '../constants.js';
@@ -423,7 +423,7 @@ export class FilterService {
423423
inputSearchTerms: SearchTerm[] | undefined,
424424
columnFilter: Omit<SearchColumnFilter, 'searchTerms'>
425425
): Omit<FilterConditionOption, 'cellValue'> {
426-
const searchValues: SearchTerm[] = extend(true, [], inputSearchTerms) || [];
426+
const searchValues: SearchTerm[] = deepCopy(inputSearchTerms) || [];
427427
let fieldSearchValue = Array.isArray(searchValues) && searchValues.length === 1 ? searchValues[0] : '';
428428
const columnDef = columnFilter.columnDef;
429429
const fieldType = columnDef.filter?.type ?? columnDef.type ?? FieldType.string;
@@ -611,7 +611,7 @@ export class FilterService {
611611
if (typeof columnFilters === 'object') {
612612
Object.keys(columnFilters).forEach((columnId) => {
613613
const columnFilter = columnFilters[columnId] as SearchColumnFilter;
614-
const searchValues: SearchTerm[] = columnFilter?.searchTerms ? extend(true, [], columnFilter.searchTerms) : [];
614+
const searchValues: SearchTerm[] = columnFilter?.searchTerms ? deepCopy(columnFilter.searchTerms) : [];
615615
const inputSearchConditions = this.parseFormInputFilterConditions(searchValues, columnFilter);
616616

617617
const columnDef = columnFilter.columnDef;

packages/composite-editor-component/src/slick-composite-editor.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { BindingEventService } from '@slickgrid-universal/binding';
2-
import { deepMerge, emptyObject, setDeepValue, classNameToList, getHtmlStringOutput, extend } from '@slickgrid-universal/utils';
2+
import { classNameToList, deepCopy, deepMerge, emptyObject, getHtmlStringOutput, setDeepValue } from '@slickgrid-universal/utils';
33
import type {
44
Column,
55
CompositeEditorLabel,
@@ -347,7 +347,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
347347
} else {
348348
const isWithMassChange = modalType === 'mass-update' || modalType === 'mass-selection';
349349
const dataContext = !isWithMassChange ? this.grid.getDataItem(activeRow) : {};
350-
this._originalDataContext = extend(true, {}, dataContext);
350+
this._originalDataContext = deepCopy(dataContext);
351351
this._columns = this.grid.getColumns();
352352
const selectedRowsIndexes = this.hasRowSelectionEnabled() ? this.grid.getSelectedRows() : [];
353353
const fullDatasetLength = this.dataView?.getItemCount() ?? 0;
@@ -645,7 +645,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
645645
/** Apply Mass Update Changes (form values) to the entire dataset */
646646
protected applySaveMassUpdateChanges(formValues: any, _selection: DataSelection, applyToDataview = true): any[] {
647647
// not applying to dataView means that we're doing a preview of dataset and we should use a deep copy of it instead of applying changes directly to it
648-
const data = applyToDataview ? this.dataView.getItems() : extend(true, [], this.dataView.getItems());
648+
const data = applyToDataview ? this.dataView.getItems() : deepCopy(this.dataView.getItems());
649649

650650
// from the "lastCompositeEditor" object that we kept as reference, it contains all the changes inside the "formValues" property
651651
// we can loop through these changes and apply them on the selected row indexes
@@ -674,7 +674,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
674674
const selectedTmpItems = selectedItemIds.map((itemId) => this.dataView.getItemById(itemId));
675675

676676
// not applying to dataView means that we're doing a preview of dataset and we should use a deep copy of it instead of applying changes directly to it
677-
const selectedItems = applyToDataview ? selectedTmpItems : extend(true, [], selectedTmpItems);
677+
const selectedItems = applyToDataview ? selectedTmpItems : deepCopy(selectedTmpItems);
678678

679679
// from the "lastCompositeEditor" object that we kept as reference, it contains all the changes inside the "formValues" property
680680
// we can loop through these changes and apply them on the selected row indexes

packages/utils/src/utils.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { AnyFunction } from './models/types.js';
2-
import { extend } from './nodeExtend.js';
32

43
/**
54
* Add an item to an array only when the item does not exists, when the item is an object we will be using their "id" to compare
@@ -44,20 +43,50 @@ export function arrayRemoveItemByIndex<T>(array: T[], index: number): T[] {
4443
}
4544

4645
/**
47-
* @use `extend()` when possible.
48-
* Create an immutable clone of an array or object (native type will be returned "as is").
49-
* This function will deep copy whatever is provided as the first argument, but nonetheless it is now an alias to `extend()` (node-extend) function.
50-
* We'll keep the method to avoid breaking users of `deepCopy()`, however we suggest to directly use `extend(true, {}, obj)` whenever possible
46+
* Create an immutable clone of an array or object
47+
* (c) 2019 Chris Ferdinandi, MIT License, https://gomakethings.com
48+
* @param {Array|Object} objectOrArray - the array or object to copy
49+
* @return {Array|Object} - the clone of the array or object
5150
*/
5251
export function deepCopy(objectOrArray: any | any[]): any | any[] {
53-
// we previously had a full implementation but we can now use node-extend to do the job
54-
// except that we need couple of small priors checks (native will be returned as is)
55-
if (!Array.isArray(objectOrArray) && !isObject(objectOrArray)) {
56-
return objectOrArray;
52+
/**
53+
* Create an immutable copy of an object
54+
* @return {Object}
55+
*/
56+
const cloneObj = () => {
57+
// Create new object
58+
const clone = {};
59+
60+
// Loop through each item in the original
61+
// Recursively copy it's value and add to the clone
62+
Object.keys(objectOrArray).forEach((key) => {
63+
if (Object.prototype.hasOwnProperty.call(objectOrArray, key)) {
64+
(clone as any)[key] = deepCopy(objectOrArray[key]);
65+
}
66+
});
67+
return clone;
68+
};
69+
70+
/**
71+
* Create an immutable copy of an array
72+
* @return {Array}
73+
*/
74+
const cloneArr = () => objectOrArray.map((item: any) => deepCopy(item));
75+
76+
// -- init --//
77+
// Get object type
78+
const type = Object.prototype.toString.call(objectOrArray).slice(8, -1).toLowerCase();
79+
80+
// If an object
81+
if (type === 'object') {
82+
return cloneObj();
83+
}
84+
// If an array
85+
if (type === 'array') {
86+
return cloneArr();
5787
}
58-
// Array or Object need 2nd arg to be either [] or {} for a deep copy to assign to when using node-extend (same as jQuery.extend())
59-
const assignment = Array.isArray(objectOrArray) ? [] : {};
60-
return extend(true, assignment, objectOrArray);
88+
// Otherwise, return it as-is
89+
return objectOrArray;
6190
}
6291

6392
/**

packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
SlickGrid,
5454
unsubscribeAll,
5555
} from '@slickgrid-universal/common';
56-
import { extend, queueMicrotaskOrSetTimeout } from '@slickgrid-universal/utils';
56+
import { deepCopy, extend, queueMicrotaskOrSetTimeout } from '@slickgrid-universal/utils';
5757
import { EventNamingStyle, EventPubSubService } from '@slickgrid-universal/event-pub-sub';
5858
import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
5959
import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component';
@@ -152,7 +152,7 @@ export class SlickVanillaGridBundle<TData = any> {
152152
const prevDatasetLn = this._currentDatasetLength;
153153
const isDatasetEqual = dequal(newDataset, this.dataset || []);
154154
const isDeepCopyDataOnPageLoadEnabled = !!this._gridOptions?.enableDeepCopyDatasetOnPageLoad;
155-
let data = isDeepCopyDataOnPageLoadEnabled ? extend(true, [], newDataset) : newDataset;
155+
let data = isDeepCopyDataOnPageLoadEnabled ? deepCopy(newDataset) : newDataset;
156156

157157
// when Tree Data is enabled and we don't yet have the hierarchical dataset filled, we can force a convert+sort of the array
158158
if (
@@ -398,7 +398,7 @@ export class SlickVanillaGridBundle<TData = any> {
398398

399399
if (hierarchicalDataset) {
400400
this.sharedService.hierarchicalDataset =
401-
(isDeepCopyDataOnPageLoadEnabled ? extend(true, [], hierarchicalDataset) : hierarchicalDataset) || [];
401+
(isDeepCopyDataOnPageLoadEnabled ? deepCopy(hierarchicalDataset) : hierarchicalDataset) || [];
402402
}
403403
const eventHandler = new SlickEventHandler();
404404

0 commit comments

Comments
 (0)