diff --git a/src/vs/base/common/decorators.ts b/src/vs/base/common/decorators.ts index f9e39b6b941..5eb4fa7ad83 100644 --- a/src/vs/base/common/decorators.ts +++ b/src/vs/base/common/decorators.ts @@ -24,64 +24,39 @@ export function createDecorator(mapFn: (fn: Function, key: string) => Function): }; } -let memoizeId = 0; -export function createMemoizer() { - const memoizeKeyPrefix = `$memoize${memoizeId++}`; - let self: any = undefined; +export function memoize(_target: any, key: string, descriptor: any) { + let fnKey: string | null = null; + let fn: Function | null = null; - const result = function memoize(target: any, key: string, descriptor: any) { - let fnKey: string | null = null; - let fn: Function | null = null; + if (typeof descriptor.value === 'function') { + fnKey = 'value'; + fn = descriptor.value; - if (typeof descriptor.value === 'function') { - fnKey = 'value'; - fn = descriptor.value; + if (fn!.length !== 0) { + console.warn('Memoize should only be used in functions with zero parameters'); + } + } else if (typeof descriptor.get === 'function') { + fnKey = 'get'; + fn = descriptor.get; + } - if (fn!.length !== 0) { - console.warn('Memoize should only be used in functions with zero parameters'); - } - } else if (typeof descriptor.get === 'function') { - fnKey = 'get'; - fn = descriptor.get; + if (!fn) { + throw new Error('not supported'); + } + + const memoizeKey = `$memoize$${key}`; + descriptor[fnKey!] = function (...args: any[]) { + if (!this.hasOwnProperty(memoizeKey)) { + Object.defineProperty(this, memoizeKey, { + configurable: false, + enumerable: false, + writable: false, + value: fn!.apply(this, args) + }); } - if (!fn) { - throw new Error('not supported'); - } - - const memoizeKey = `${memoizeKeyPrefix}:${key}`; - descriptor[fnKey!] = function (...args: any[]) { - self = this; - - if (!this.hasOwnProperty(memoizeKey)) { - Object.defineProperty(this, memoizeKey, { - configurable: true, - enumerable: false, - writable: true, - value: fn!.apply(this, args) - }); - } - - return this[memoizeKey]; - }; + return this[memoizeKey]; }; - - result.clear = () => { - if (typeof self === 'undefined') { - return; - } - Object.getOwnPropertyNames(self).forEach(property => { - if (property.indexOf(memoizeKeyPrefix) === 0) { - delete self[property]; - } - }); - }; - - return result; -} - -export function memoize(target: any, key: string, descriptor: any) { - return createMemoizer()(target, key, descriptor); } export interface IDebounceReducer { diff --git a/src/vs/base/test/common/decorators.test.ts b/src/vs/base/test/common/decorators.test.ts index 0e88e4f2ec0..87300310650 100644 --- a/src/vs/base/test/common/decorators.test.ts +++ b/src/vs/base/test/common/decorators.test.ts @@ -5,7 +5,7 @@ import * as sinon from 'sinon'; import * as assert from 'assert'; -import { memoize, createMemoizer, throttle } from 'vs/base/common/decorators'; +import { memoize, throttle } from 'vs/base/common/decorators'; suite('Decorators', () => { test('memoize should memoize methods', () => { @@ -131,28 +131,6 @@ suite('Decorators', () => { } }); - test('memoize clear', () => { - const memoizer = createMemoizer(); - let counter = 0; - class Foo { - @memoizer - get answer() { - return ++counter; - } - } - - const foo = new Foo(); - assert.strictEqual(foo.answer, 1); - assert.strictEqual(foo.answer, 1); - memoizer.clear(); - assert.strictEqual(foo.answer, 2); - assert.strictEqual(foo.answer, 2); - memoizer.clear(); - assert.strictEqual(foo.answer, 3); - assert.strictEqual(foo.answer, 3); - assert.strictEqual(foo.answer, 3); - }); - test('throttle', () => { const spy = sinon.spy(); const clock = sinon.useFakeTimers(); diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index c4a86e5c53c..edec9fd5d18 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -30,7 +30,7 @@ import { ExceptionWidget } from 'vs/workbench/contrib/debug/browser/exceptionWid import { FloatingClickWidget } from 'vs/workbench/browser/codeeditor'; import { Position } from 'vs/editor/common/core/position'; import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; -import { memoize, createMemoizer } from 'vs/base/common/decorators'; +import { memoize } from 'vs/base/common/decorators'; import { IEditorHoverOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; import { DebugHoverWidget } from 'vs/workbench/contrib/debug/browser/debugHover'; import { ITextModel } from 'vs/editor/common/model'; @@ -185,7 +185,6 @@ export class DebugEditorContribution implements IDebugEditorContribution { private hoverRange: Range | null = null; private mouseDown = false; private exceptionWidgetVisible: IContextKey; - private static readonly MEMOIZER = createMemoizer(); private exceptionWidget: ExceptionWidget | undefined; private configurationWidget: FloatingClickWidget | undefined; @@ -234,7 +233,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { })); this.toDispose.push(this.editor.onKeyDown((e: IKeyboardEvent) => this.onKeyDown(e))); this.toDispose.push(this.editor.onDidChangeModelContent(() => { - DebugEditorContribution.MEMOIZER.clear(); + this._wordToLineNumbersMap = undefined; this.updateInlineValuesScheduler.schedule(); })); this.toDispose.push(this.debugService.getViewModel().onWillUpdateViews(() => this.updateInlineValuesScheduler.schedule())); @@ -247,7 +246,7 @@ export class DebugEditorContribution implements IDebugEditorContribution { this.toggleExceptionWidget(); this.hideHoverWidget(); this.updateConfigurationWidgetVisibility(); - DebugEditorContribution.MEMOIZER.clear(); + this._wordToLineNumbersMap = undefined; await this.updateInlineValueDecorations(stackFrame); })); this.toDispose.push(this.editor.onDidScrollChange(() => { @@ -266,9 +265,12 @@ export class DebugEditorContribution implements IDebugEditorContribution { })); } - @DebugEditorContribution.MEMOIZER + private _wordToLineNumbersMap: Map | undefined = undefined; private get wordToLineNumbersMap(): Map { - return getWordToLineNumbersMap(this.editor.getModel()); + if (!this._wordToLineNumbersMap) { + this._wordToLineNumbersMap = getWordToLineNumbersMap(this.editor.getModel()); + } + return this._wordToLineNumbersMap; } private applyHoverConfiguration(model: ITextModel, stackFrame: IStackFrame | undefined): void { diff --git a/src/vs/workbench/contrib/webview/browser/themeing.ts b/src/vs/workbench/contrib/webview/browser/themeing.ts index 06b670208a3..8232566cde6 100644 --- a/src/vs/workbench/contrib/webview/browser/themeing.ts +++ b/src/vs/workbench/contrib/webview/browser/themeing.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createMemoizer } from 'vs/base/common/decorators'; import { Disposable } from 'vs/base/common/lifecycle'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -22,8 +21,7 @@ interface WebviewThemeData { export class WebviewThemeDataProvider extends Disposable { - - private static readonly MEMOIZER = createMemoizer(); + private _cachedWebViewThemeData: WebviewThemeData | undefined = undefined; private readonly _onThemeDataChanged = this._register(new Emitter()); public readonly onThemeDataChanged = this._onThemeDataChanged.event; @@ -50,38 +48,41 @@ export class WebviewThemeDataProvider extends Disposable { return this._themeService.getColorTheme(); } - @WebviewThemeDataProvider.MEMOIZER public getWebviewThemeData(): WebviewThemeData { - const configuration = this._configurationService.getValue('editor'); - const editorFontFamily = configuration.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; - const editorFontWeight = configuration.fontWeight || EDITOR_FONT_DEFAULTS.fontWeight; - const editorFontSize = configuration.fontSize || EDITOR_FONT_DEFAULTS.fontSize; + if (!this._cachedWebViewThemeData) { + const configuration = this._configurationService.getValue('editor'); + const editorFontFamily = configuration.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; + const editorFontWeight = configuration.fontWeight || EDITOR_FONT_DEFAULTS.fontWeight; + const editorFontSize = configuration.fontSize || EDITOR_FONT_DEFAULTS.fontSize; - const theme = this._themeService.getColorTheme(); - const exportedColors = colorRegistry.getColorRegistry().getColors().reduce((colors, entry) => { - const color = theme.getColor(entry.id); - if (color) { - colors['vscode-' + entry.id.replace('.', '-')] = color.toString(); - } - return colors; - }, {} as { [key: string]: string; }); + const theme = this._themeService.getColorTheme(); + const exportedColors = colorRegistry.getColorRegistry().getColors().reduce((colors, entry) => { + const color = theme.getColor(entry.id); + if (color) { + colors['vscode-' + entry.id.replace('.', '-')] = color.toString(); + } + return colors; + }, {} as { [key: string]: string; }); - const styles = { - 'vscode-font-family': DEFAULT_FONT_FAMILY, - 'vscode-font-weight': 'normal', - 'vscode-font-size': '13px', - 'vscode-editor-font-family': editorFontFamily, - 'vscode-editor-font-weight': editorFontWeight, - 'vscode-editor-font-size': editorFontSize + 'px', - ...exportedColors - }; + const styles = { + 'vscode-font-family': DEFAULT_FONT_FAMILY, + 'vscode-font-weight': 'normal', + 'vscode-font-size': '13px', + 'vscode-editor-font-family': editorFontFamily, + 'vscode-editor-font-weight': editorFontWeight, + 'vscode-editor-font-size': editorFontSize + 'px', + ...exportedColors + }; - const activeTheme = ApiThemeClassName.fromTheme(theme); - return { styles, activeTheme, themeLabel: theme.label, }; + const activeTheme = ApiThemeClassName.fromTheme(theme); + this._cachedWebViewThemeData = { styles, activeTheme, themeLabel: theme.label, }; + } + + return this._cachedWebViewThemeData; } private reset() { - WebviewThemeDataProvider.MEMOIZER.clear(); + this._cachedWebViewThemeData = undefined; this._onThemeDataChanged.fire(); } }