Merge pull request #5933 from xtermjs/cursor/replace-clone-with-structuredclone-34fc
Replace custom clone utility with structuredClone
This commit is contained in:
@@ -1,129 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { assert } from 'chai';
|
|
||||||
import { clone } from 'common/Clone';
|
|
||||||
|
|
||||||
describe('clone', () => {
|
|
||||||
it('should clone simple objects', () => {
|
|
||||||
const test = {
|
|
||||||
a: 1,
|
|
||||||
b: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.deepEqual(clone(test), { a: 1, b: 2 });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone nested objects', () => {
|
|
||||||
const test = {
|
|
||||||
bar: {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
c: {
|
|
||||||
foo: 'bar'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.deepEqual(clone(test), {
|
|
||||||
bar: {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
c: {
|
|
||||||
foo: 'bar'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone array values', () => {
|
|
||||||
const test = {
|
|
||||||
a: [1, 2, 3],
|
|
||||||
b: [1, null, 'test', { foo: 'bar' }]
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.deepEqual(clone(test), {
|
|
||||||
a: [1, 2, 3],
|
|
||||||
b: [1, null, 'test', { foo: 'bar' }]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should stop mutation from occuring on the original object', () => {
|
|
||||||
const test = {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
c: {
|
|
||||||
foo: 'bar'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const cloned = clone(test);
|
|
||||||
|
|
||||||
test.a = 5;
|
|
||||||
test.c.foo = 'barbaz';
|
|
||||||
|
|
||||||
assert.deepEqual(cloned, {
|
|
||||||
a: 1,
|
|
||||||
b: 2,
|
|
||||||
c: {
|
|
||||||
foo: 'bar'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should clone to a maximum depth of 5 by default', () => {
|
|
||||||
const test = {
|
|
||||||
a: {
|
|
||||||
b: {
|
|
||||||
c: {
|
|
||||||
d: {
|
|
||||||
e: {
|
|
||||||
f: 'foo'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const cloned = clone(test);
|
|
||||||
|
|
||||||
test.a.b.c.d.e.f = 'bar';
|
|
||||||
|
|
||||||
// The values at a greater depth then 5 should not be cloned
|
|
||||||
assert.equal((cloned as any).a.b.c.d.e.f, 'bar');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow an optional maximum depth to be set', () => {
|
|
||||||
const test = {
|
|
||||||
a: {
|
|
||||||
b: {
|
|
||||||
c: 'foo'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const cloned = clone(test, 2);
|
|
||||||
|
|
||||||
test.a.b.c = 'bar';
|
|
||||||
|
|
||||||
// The values at a greater depth then 2 should not be cloned
|
|
||||||
assert.equal((cloned as any).a.b.c, 'bar');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not throw when cloning a recursive reference', () => {
|
|
||||||
const test = {
|
|
||||||
a: {
|
|
||||||
b: {
|
|
||||||
c: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
test.a.b.c = test;
|
|
||||||
|
|
||||||
assert.doesNotThrow(() => clone(test));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A simple utility for cloning values
|
|
||||||
*/
|
|
||||||
export function clone<T>(val: T, depth: number = 5): T {
|
|
||||||
if (typeof val !== 'object') {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're cloning an array, use an array as the base, otherwise use an object
|
|
||||||
const clonedObject: any = Array.isArray(val) ? [] : {};
|
|
||||||
|
|
||||||
for (const key in val) {
|
|
||||||
// Recursively clone eack item unless we're at the maximum depth
|
|
||||||
clonedObject[key] = depth <= 1 ? val[key] : (val[key] && clone(val[key], depth - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return clonedObject as T;
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,6 @@ import { Params } from 'common/parser/Params';
|
|||||||
import { MockCoreService, MockBufferService, MockOptionsService, MockLogService, MockMouseStateService, MockCharsetService, MockUnicodeService, MockOscLinkService, extendedAttributes } from 'common/TestUtils.test';
|
import { MockCoreService, MockBufferService, MockOptionsService, MockLogService, MockMouseStateService, MockCharsetService, MockUnicodeService, MockOscLinkService, extendedAttributes } from 'common/TestUtils.test';
|
||||||
import { IBufferService, ICoreService, type IOscLinkService } from 'common/services/Services';
|
import { IBufferService, ICoreService, type IOscLinkService } from 'common/services/Services';
|
||||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||||
import { clone } from 'common/Clone';
|
|
||||||
import { BufferService } from 'common/services/BufferService';
|
import { BufferService } from 'common/services/BufferService';
|
||||||
import { CoreService } from 'common/services/CoreService';
|
import { CoreService } from 'common/services/CoreService';
|
||||||
import { OscLinkService } from 'common/services/OscLinkService';
|
import { OscLinkService } from 'common/services/OscLinkService';
|
||||||
@@ -227,32 +226,32 @@ describe('InputHandler', () => {
|
|||||||
assert.equal(coreService.decPrivateModes.cursorStyle, undefined);
|
assert.equal(coreService.decPrivateModes.cursorStyle, undefined);
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, undefined);
|
assert.equal(coreService.decPrivateModes.cursorBlink, undefined);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([1]));
|
inputHandler.setCursorStyle(Params.fromArray([1]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([2]));
|
inputHandler.setCursorStyle(Params.fromArray([2]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'block');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([3]));
|
inputHandler.setCursorStyle(Params.fromArray([3]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([4]));
|
inputHandler.setCursorStyle(Params.fromArray([4]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'underline');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([5]));
|
inputHandler.setCursorStyle(Params.fromArray([5]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
assert.equal(coreService.decPrivateModes.cursorBlink, true);
|
||||||
|
|
||||||
optionsService.options = clone(DEFAULT_OPTIONS);
|
optionsService.options = structuredClone(DEFAULT_OPTIONS);
|
||||||
inputHandler.setCursorStyle(Params.fromArray([6]));
|
inputHandler.setCursorStyle(Params.fromArray([6]));
|
||||||
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
|
assert.equal(coreService.decPrivateModes.cursorStyle, 'bar');
|
||||||
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
assert.equal(coreService.decPrivateModes.cursorBlink, false);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IMouseStateService, ICharsetService, UnicodeCharProperties, UnicodeCharWidth, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum, IDecorationService, IInternalDecoration, IOscLinkService, type IBufferResizeEvent } from 'common/services/Services';
|
import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IMouseStateService, ICharsetService, UnicodeCharProperties, UnicodeCharWidth, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum, IDecorationService, IInternalDecoration, IOscLinkService, type IBufferResizeEvent } from 'common/services/Services';
|
||||||
import { UnicodeService } from 'common/services/UnicodeService';
|
import { UnicodeService } from 'common/services/UnicodeService';
|
||||||
import { clone } from 'common/Clone';
|
|
||||||
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
|
||||||
import { IBufferSet, IBuffer } from 'common/buffer/Types';
|
import { IBufferSet, IBuffer } from 'common/buffer/Types';
|
||||||
import { BufferSet } from 'common/buffer/BufferSet';
|
import { BufferSet } from 'common/buffer/BufferSet';
|
||||||
@@ -157,7 +156,7 @@ export class MockLogService implements ILogService {
|
|||||||
|
|
||||||
export class MockOptionsService implements IOptionsService {
|
export class MockOptionsService implements IOptionsService {
|
||||||
public serviceBrand: any;
|
public serviceBrand: any;
|
||||||
public readonly rawOptions: Required<ITerminalOptions> = clone(DEFAULT_OPTIONS);
|
public readonly rawOptions: Required<ITerminalOptions> = structuredClone(DEFAULT_OPTIONS);
|
||||||
public options: Required<ITerminalOptions> = this.rawOptions;
|
public options: Required<ITerminalOptions> = this.rawOptions;
|
||||||
public onOptionChange: IEvent<keyof ITerminalOptions> = new Emitter<keyof ITerminalOptions>().event;
|
public onOptionChange: IEvent<keyof ITerminalOptions> = new Emitter<keyof ITerminalOptions>().event;
|
||||||
constructor(testOptions?: Partial<ITerminalOptions>) {
|
constructor(testOptions?: Partial<ITerminalOptions>) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { clone } from 'common/Clone';
|
|
||||||
import { Disposable } from 'common/Lifecycle';
|
import { Disposable } from 'common/Lifecycle';
|
||||||
import { IDecPrivateModes, IKittyKeyboardState, IModes } from 'common/Types';
|
import { IDecPrivateModes, IKittyKeyboardState, IModes } from 'common/Types';
|
||||||
import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
|
import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
|
||||||
@@ -61,14 +60,14 @@ export class CoreService extends Disposable implements ICoreService {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.isCursorInitialized = _optionsService.rawOptions.showCursorImmediately ?? false;
|
this.isCursorInitialized = _optionsService.rawOptions.showCursorImmediately ?? false;
|
||||||
this.modes = clone(DEFAULT_MODES);
|
this.modes = structuredClone(DEFAULT_MODES);
|
||||||
this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
|
this.decPrivateModes = structuredClone(DEFAULT_DEC_PRIVATE_MODES);
|
||||||
this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
|
this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
|
||||||
}
|
}
|
||||||
|
|
||||||
public reset(): void {
|
public reset(): void {
|
||||||
this.modes = clone(DEFAULT_MODES);
|
this.modes = structuredClone(DEFAULT_MODES);
|
||||||
this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);
|
this.decPrivateModes = structuredClone(DEFAULT_DEC_PRIVATE_MODES);
|
||||||
this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
|
this.kittyKeyboard = DEFAULT_KITTY_KEYBOARD_STATE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user