Skip to content

Commit 6602a24

Browse files
underootgithub-actions[bot]
authored andcommitted
Migrate from clone to structuredClone
GitOrigin-RevId: ce20da79c46a6a1150635e2305748e60f824f061
1 parent 17721a0 commit 6602a24

5 files changed

Lines changed: 20 additions & 65 deletions

File tree

.browserslistrc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@
1010
#
1111
# Browser | Limiting Feature | Min
1212
# ---------------|-----------------------|----
13-
# Chrome | Object.hasOwn | 93
13+
# Chrome | structuredClone | 98
1414
# Safari | Array.at | 15.4
1515
# Firefox | Object.hasOwn | 115
16-
# Edge | Object.hasOwn | 93
17-
# Chrome Android | Object.hasOwn | 93
16+
# Edge | structuredClone | 98
17+
# Chrome Android | structuredClone | 98
1818
# iOS Safari | Array.at | 15.4
1919

2020
chrome >= 93
2121
safari >= 15.4
2222
firefox >= 115
23-
edge >= 93
24-
and_chr >= 93
23+
edge >= 98
24+
and_chr >= 98
2525
ios_saf >= 15.4

src/style/properties.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from '../style-spec/util/assert';
2-
import {clone, easeCubicInOut, sphericalDirectionToCartesian, sphericalPositionToCartesian} from '../util/util';
2+
import {easeCubicInOut, sphericalDirectionToCartesian, sphericalPositionToCartesian} from '../util/util';
33
import * as interpolate from '../style-spec/util/interpolate';
44
import {number as interpolateValue} from '../style-spec/util/interpolate';
55
import {normalizePropertyExpression} from '../style-spec/expression/index';
@@ -209,7 +209,7 @@ export class Transitionable<Props extends {[Key in keyof Props]: Props[Key]}> {
209209
}
210210

211211
getValue<S extends keyof Props, T>(name: S): PropertyValueSpecification<T> | undefined {
212-
return clone(this._values[name].value.value as PropertyValueSpecification<T> | undefined);
212+
return structuredClone(this._values[name].value.value as PropertyValueSpecification<T> | undefined);
213213
}
214214

215215
setValue<S extends keyof Props, T>(name: S, value?: PropertyValueSpecification<T>) {
@@ -218,7 +218,7 @@ export class Transitionable<Props extends {[Key in keyof Props]: Props[Key]}> {
218218
}
219219
// Note that we do not _remove_ an own property in the case where a value is being reset
220220
// to the default: the transition might still be non-default.
221-
this._values[name].value = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value), this._scope, this._options, this._iconImageUseTheme);
221+
this._values[name].value = new PropertyValue(this._values[name].property, value === null ? undefined : structuredClone(value), this._scope, this._options, this._iconImageUseTheme);
222222
if (this._values[name].value.expression.configDependencies) {
223223
this.configDependencies = new Set([...this.configDependencies, ...this._values[name].value.expression.configDependencies]);
224224
this._isIndoorDependent = this._isIndoorDependent || this._values[name].value.isIndoorDependent();
@@ -245,14 +245,14 @@ export class Transitionable<Props extends {[Key in keyof Props]: Props[Key]}> {
245245
}
246246

247247
getTransition<S extends keyof Props>(name: S): TransitionSpecification | undefined {
248-
return clone(this._values[name].transition);
248+
return structuredClone(this._values[name].transition);
249249
}
250250

251251
setTransition<S extends keyof Props>(name: S, value?: TransitionSpecification) {
252252
if (!Object.hasOwn(this._values, name)) {
253253
this._values[name] = new TransitionablePropertyValue(this._values[name].property) as TransitionablePropertyValues<Props>[S];
254254
}
255-
this._values[name].transition = clone(value) || undefined;
255+
this._values[name].transition = structuredClone(value) || undefined;
256256
}
257257

258258
serialize(): PropertyValueSpecifications<Props> {
@@ -474,11 +474,11 @@ export class Layout<Props extends {
474474
}
475475

476476
getValue<S extends keyof Props, T>(name: S): PropertyValueSpecification<T> | void {
477-
return clone(this._values[name].value as PropertyValueSpecification<T> | void);
477+
return structuredClone(this._values[name].value as PropertyValueSpecification<T> | void);
478478
}
479479

480480
setValue<S extends keyof Props>(name: S, value: unknown) {
481-
this._values[name] = new PropertyValue(this._values[name].property, value === null ? undefined : clone(value), this._scope, this._options, this._iconImageUseTheme) as PropertyValues<Props>[S];
481+
this._values[name] = new PropertyValue(this._values[name].property, value === null ? undefined : structuredClone(value), this._scope, this._options, this._iconImageUseTheme) as PropertyValues<Props>[S];
482482
if (this._values[name].expression.configDependencies) {
483483
this.configDependencies = new Set([...this.configDependencies, ...this._values[name].expression.configDependencies]);
484484
this._isIndoorDependent = this._isIndoorDependent || this._values[name].isIndoorDependent();

src/style/style.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Terrain, {DrapeRenderMode} from './terrain';
1111
import Fog from './fog';
1212
import Snow from './snow';
1313
import Rain from './rain';
14-
import {pick, clone, deepEqual, filterObject, cartesianPositionToSpherical, warnOnce} from '../util/util';
14+
import {pick, deepEqual, filterObject, cartesianPositionToSpherical, warnOnce} from '../util/util';
1515
import {getJSON, getReferrer, ResourceType} from '../util/ajax';
1616
import {isMapboxURL} from '../util/mapbox_url';
1717
import {stripQueryParameters} from '../util/url';
@@ -918,7 +918,7 @@ class Style extends Evented<MapEvents> {
918918
this.addSource(id, json.sources[id], {validate: false, isInitialLoad: true});
919919
}
920920

921-
this.stylesheet = clone(json);
921+
this.stylesheet = structuredClone(json);
922922

923923
const proceedWithStyleLoad = () => {
924924
if (json.iconsets) {
@@ -2212,7 +2212,7 @@ class Style extends Evented<MapEvents> {
22122212

22132213
if (emitValidationErrors(this, validateStyle(nextState))) return false;
22142214

2215-
nextState = clone(nextState);
2215+
nextState = structuredClone(nextState);
22162216
nextState.layers = deref(nextState.layers);
22172217

22182218
const changes = diffStyles(this.serialize(), nextState)
@@ -2984,7 +2984,7 @@ class Style extends Evented<MapEvents> {
29842984
} else {
29852985
if (typeof layerObject.source === 'object') {
29862986
this.addSource(id, layerObject.source);
2987-
layerObject = clone(layerObject);
2987+
layerObject = structuredClone(layerObject);
29882988
layerObject = (Object.assign(layerObject, {source: id}));
29892989
}
29902990

@@ -3242,7 +3242,7 @@ class Style extends Evented<MapEvents> {
32423242
return;
32433243
}
32443244

3245-
layer.filter = clone(filter);
3245+
layer.filter = structuredClone(filter);
32463246
this._updateLayer(layer);
32473247
}
32483248

@@ -3254,7 +3254,7 @@ class Style extends Evented<MapEvents> {
32543254
getFilter(layerId: string): FilterSpecification | null | undefined {
32553255
const layer = this._checkLayer(layerId);
32563256
if (!layer) return;
3257-
return clone(layer.filter);
3257+
return structuredClone(layer.filter);
32583258
}
32593259

32603260
setLayoutProperty<T extends keyof LayoutSpecification>(layerId: string, name: T, value: LayoutSpecification[T], options: StyleSetterOptions = {}) {
@@ -4000,7 +4000,7 @@ class Style extends Evented<MapEvents> {
40004000
if ("source" in options && typeof options.source === 'object') {
40014001
const id = 'terrain-dem-src';
40024002
this.addSource(id, options.source);
4003-
options = clone(options);
4003+
options = structuredClone(options);
40044004
options = Object.assign(options, {source: id});
40054005
}
40064006

src/util/util.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -447,21 +447,6 @@ export function filterObject<T extends Record<PropertyKey, unknown>>(
447447
return output;
448448
}
449449

450-
/**
451-
* Deeply clones two objects.
452-
*
453-
* @private
454-
*/
455-
export function clone<T>(input: T): T {
456-
if (Array.isArray(input)) {
457-
return input.map(clone) as T;
458-
} else if (typeof input === 'object' && input) {
459-
return mapObject(input as Record<PropertyKey, unknown>, clone) as T;
460-
} else {
461-
return input;
462-
}
463-
}
464-
465450
/**
466451
* Maps a value from a range between [min, max] to the range [outMin, outMax]
467452
*

test/unit/util/util.test.ts

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// @ts-nocheck
33
import Point from '@mapbox/point-geometry';
44
import {describe, test, expect} from '../../util/vitest';
5-
import {mapValue, degToRad, radToDeg, easeCubicInOut, getAABBPointSquareDist, furthestTileCorner, keysDifference, pick, uniqueId, bindAll, asyncAll, clamp, smoothstep, wrap, bezier, mapObject, filterObject, deepEqual, clone, arraysIntersect, isCounterClockwise, parseCacheControl, parseExpiryData, uuid, validateUuid, nextPowerOfTwo, isPowerOfTwo, bufferConvexPolygon, prevPowerOfTwo, shortestAngle} from '../../../src/util/util';
5+
import {mapValue, degToRad, radToDeg, easeCubicInOut, getAABBPointSquareDist, furthestTileCorner, keysDifference, pick, uniqueId, bindAll, asyncAll, clamp, smoothstep, wrap, bezier, mapObject, filterObject, deepEqual, arraysIntersect, isCounterClockwise, parseCacheControl, parseExpiryData, uuid, validateUuid, nextPowerOfTwo, isPowerOfTwo, bufferConvexPolygon, prevPowerOfTwo, shortestAngle} from '../../../src/util/util';
66

77
const EPSILON = 1e-8;
88

@@ -265,36 +265,6 @@ describe('util', () => {
265265
expect(deepEqual(null, null)).toBeTruthy();
266266
});
267267

268-
describe('clone', () => {
269-
test('array', () => {
270-
const input = [false, 1, 'two'];
271-
const output = clone(input);
272-
expect(input).not.toBe(output);
273-
expect(input).toEqual(output);
274-
});
275-
276-
test('object', () => {
277-
const input = {a: false, b: 1, c: 'two'};
278-
const output = clone(input);
279-
expect(input).not.toBe(output);
280-
expect(input).toEqual(output);
281-
});
282-
283-
test('deep object', () => {
284-
const input = {object: {a: false, b: 1, c: 'two'}};
285-
const output = clone(input);
286-
expect(input.object).not.toBe(output.object);
287-
expect(input.object).toEqual(output.object);
288-
});
289-
290-
test('deep array', () => {
291-
const input = {array: [false, 1, 'two']};
292-
const output = clone(input);
293-
expect(input.array).not.toBe(output.array);
294-
expect(input.array).toEqual(output.array);
295-
});
296-
});
297-
298268
describe('arraysIntersect', () => {
299269
test('intersection', () => {
300270
const a = ["1", "2", "3"];

0 commit comments

Comments
 (0)