From 100e9d0d98c243013ecbbfcc61b8df7393fbcfe5 Mon Sep 17 00:00:00 2001 From: Martin Fleck Date: Fri, 8 Mar 2024 09:52:27 +0100 Subject: [PATCH] Consider PR feedback - Move evaluation expression for addressOf and sizeOf to adapter - Make 'toHexStringWithRadixMarker' more flexible - Shorten validation messages for memory - Align props and method names with existing method names, no prefixes - Replace 'MemoryVariableNode' with 'IVariablesContext' - Add comment on overlap calculation --- src/common/debug-requests.ts | 22 ++++++---- src/common/memory-range.ts | 4 +- src/common/memory.ts | 35 +++++----------- src/common/messaging.ts | 4 +- .../adapter-registry/adapter-capabilities.ts | 24 +++++++++-- src/plugin/adapter-registry/c-tracker.ts | 40 ++++++++++++++----- src/plugin/external-views.ts | 32 +++++++++++++++ src/plugin/memory-provider.ts | 16 ++++++-- src/plugin/memory-storage.ts | 21 +++++----- src/plugin/memory-webview-main.ts | 11 ++--- src/webview/components/memory-table.tsx | 11 +++-- src/webview/components/memory-widget.tsx | 15 ++++--- src/webview/components/options-widget.tsx | 13 +++--- src/webview/memory-webview-view.tsx | 14 ++++--- 14 files changed, 168 insertions(+), 94 deletions(-) create mode 100644 src/plugin/external-views.ts diff --git a/src/common/debug-requests.ts b/src/common/debug-requests.ts index 7dbb8e1..4313a3a 100644 --- a/src/common/debug-requests.ts +++ b/src/common/debug-requests.ts @@ -29,11 +29,17 @@ export async function sendRequest(session: De return session.customRequest(command, args); } -export namespace EvaluateExpression { - export function sizeOf(expression: string): string { - return `sizeof(${expression})`; - } - export function addressOf(expression: string): string { - return `&(${expression})`; - } -}; +export function isDebugVariable(variable: DebugProtocol.Variable | unknown): variable is DebugProtocol.Variable { + const assumed = variable ? variable as DebugProtocol.Variable : undefined; + return typeof assumed?.name === 'string' && typeof assumed?.value === 'string'; +} + +export function isDebugScope(scope: DebugProtocol.Scope | unknown): scope is DebugProtocol.Scope { + const assumed = scope ? scope as DebugProtocol.Scope : undefined; + return typeof assumed?.name === 'string' && typeof assumed?.variablesReference === 'number'; +} + +export function isDebugEvaluateArguments(args: DebugProtocol.EvaluateArguments | unknown): args is DebugProtocol.EvaluateArguments { + const assumed = args ? args as DebugProtocol.EvaluateArguments : undefined; + return typeof assumed?.expression === 'string'; +} diff --git a/src/common/memory-range.ts b/src/common/memory-range.ts index c7c6170..48a0cdd 100644 --- a/src/common/memory-range.ts +++ b/src/common/memory-range.ts @@ -91,7 +91,7 @@ export function getRadixMarker(radix: Radix): string { return radixPrefixMap[radix]; } -export function getAddressString(address: bigint, radix: Radix, paddedLength: number = 0): string { +export function getAddressString(address: bigint | number, radix: Radix, paddedLength: number = 0): string { return address.toString(radix).padStart(paddedLength, '0'); } @@ -99,7 +99,7 @@ export function getAddressLength(padding: number, radix: Radix): number { return Math.ceil(padding / Math.log2(radix)); } -export function toHexStringWithRadixMarker(target: bigint, paddedLength: number = 0): string { +export function toHexStringWithRadixMarker(target: bigint | number, paddedLength: number = 0): string { return `${getRadixMarker(Radix.Hexadecimal)}${getAddressString(target, Radix.Hexadecimal, paddedLength)}`; } diff --git a/src/common/memory.ts b/src/common/memory.ts index d3a79ea..8101555 100644 --- a/src/common/memory.ts +++ b/src/common/memory.ts @@ -14,16 +14,19 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import type { DebugProtocol } from '@vscode/debugprotocol'; -import { ReadMemoryResult } from './messaging'; +import { ReadMemoryArguments, ReadMemoryResult } from './messaging'; export interface Memory { address: bigint; bytes: Uint8Array; } -export function createMemoryFromRead(result: ReadMemoryResult): Memory { - if (!result?.data) { throw new Error('No memory provided!'); } +export function createMemoryFromRead(result: ReadMemoryResult, request?: ReadMemoryArguments): Memory { + if (!result?.data) { + const message = request ? `No memory provided for address ${request.memoryReference}` + + `, offset ${request.offset} and count ${request.count}!` : 'No memory provided.'; + throw new Error(message); + } const address = BigInt(result.address); const bytes = stringToBytesMemory(result.data); return { bytes, address }; @@ -40,35 +43,19 @@ export function bytesToStringMemory(data: Uint8Array): string { export function validateMemoryReference(reference: string): string | undefined { const asNumber = Number(reference); // we allow an address that is not a number, e.g., an expression, but if it is a number it must be >= 0 - return !isNaN(asNumber) && asNumber < 0 ? 'Value needs to be >= 0' : undefined; + return !isNaN(asNumber) && asNumber < 0 ? 'Value must be >= 0' : undefined; } export function validateOffset(offset: string): string | undefined { const asNumber = Number(offset); - return isNaN(asNumber) ? 'No number provided' : undefined; + return isNaN(asNumber) ? 'Must be number' : undefined; } export function validateCount(count: string): string | undefined { const asNumber = Number(count); if (isNaN(asNumber)) { - return 'No number provided'; + return 'Must be number'; } else if (asNumber <= 0) { - return 'Value needs to be > 0'; + return 'Value must be > 0'; } } - -export interface MemoryVariable extends DebugProtocol.Variable { - memoryReference: string; -} - -export const isMemoryVariable = (variable: unknown): variable is MemoryVariable => !!variable && !!(variable as MemoryVariable).memoryReference; - -export interface MemoryVariableNode { - variable: MemoryVariable; - sessionId: string; -} - -export const isMemoryVariableNode = (node: unknown): node is MemoryVariableNode => - !!node - && isMemoryVariable((node as MemoryVariableNode).variable) - && typeof (node as MemoryVariableNode).sessionId === 'string'; diff --git a/src/common/messaging.ts b/src/common/messaging.ts index 68ae880..030fc97 100644 --- a/src/common/messaging.ts +++ b/src/common/messaging.ts @@ -19,8 +19,8 @@ import type { NotificationType, RequestType } from 'vscode-messenger-common'; import { MemoryViewSettings } from '../webview/utils/view-types'; import type { VariableRange, WrittenMemory } from './memory-range'; import { DebugRequestTypes } from './debug-requests'; -import { MemoryVariableNode } from './memory'; import { URI } from 'vscode-uri'; +import { VariablesView } from '../plugin/external-views'; // convenience types for easier readability and better semantics export type MemoryOptions = Partial; @@ -31,7 +31,7 @@ export type ReadMemoryResult = DebugRequestTypes['readMemory'][1]; export type WriteMemoryArguments = DebugRequestTypes['writeMemory'][0] & { count?: number }; export type WriteMemoryResult = DebugRequestTypes['writeMemory'][1]; -export type StoreMemoryArguments = MemoryOptions | MemoryVariableNode; +export type StoreMemoryArguments = MemoryOptions & { proposedOutputName?: string } | VariablesView.IVariablesContext; export type StoreMemoryResult = void; export type ApplyMemoryArguments = URI | undefined; diff --git a/src/plugin/adapter-registry/adapter-capabilities.ts b/src/plugin/adapter-registry/adapter-capabilities.ts index b07beac..d0512aa 100644 --- a/src/plugin/adapter-registry/adapter-capabilities.ts +++ b/src/plugin/adapter-registry/adapter-capabilities.ts @@ -25,6 +25,10 @@ export interface AdapterCapabilities { getVariables?(session: vscode.DebugSession): Promise; /** Resolve symbols resident in the memory at the specified range. Will be preferred to {@link getVariables} if present. */ getResidents?(session: vscode.DebugSession, params: DebugProtocol.ReadMemoryArguments): Promise; + /** Resolves the address of a given variable in bytes withthe current context. */ + getAddressOfVariable?(session: vscode.DebugSession, variableName: string): Promise; + /** Resolves the size of a given variable in bytes within the current context. */ + getSizeOfVariable?(session: vscode.DebugSession, variableName: string): Promise; initializeAdapterTracker?(session: vscode.DebugSession): vscode.DebugAdapterTracker | undefined; } @@ -106,9 +110,15 @@ export class AdapterVariableTracker implements vscode.DebugAdapterTracker { protected variableToVariableRange(_variable: DebugProtocol.Variable, _session: vscode.DebugSession): Promise { throw new Error('To be implemented by derived classes!'); } + + /** Resolves the address of a given variable in bytes withthe current context. */ + getAddressOfVariable?(variableName: string, session: vscode.DebugSession): Promise; + + /** Resolves the size of a given variable in bytes within the current context. */ + getSizeOfVariable?(variableName: string, session: vscode.DebugSession): Promise; } -export class VariableTracker { +export class VariableTracker implements AdapterCapabilities { protected sessions = new Map(); protected types: string[]; @@ -127,8 +137,16 @@ export class VariableTracker { } } - getVariables(session: vscode.DebugSession): Promise { - return Promise.resolve(this.sessions.get(session.id)?.getLocals(session) ?? []); + async getVariables(session: vscode.DebugSession): Promise { + return this.sessions.get(session.id)?.getLocals(session) ?? []; + } + + async getAddressOfVariable(session: vscode.DebugSession, variableName: string): Promise { + return this.sessions.get(session.id)?.getAddressOfVariable?.(variableName, session); + } + + async getSizeOfVariable(session: vscode.DebugSession, variableName: string): Promise { + return this.sessions.get(session.id)?.getSizeOfVariable?.(variableName, session); } } diff --git a/src/plugin/adapter-registry/c-tracker.ts b/src/plugin/adapter-registry/c-tracker.ts index f9ce943..689cc29 100644 --- a/src/plugin/adapter-registry/c-tracker.ts +++ b/src/plugin/adapter-registry/c-tracker.ts @@ -18,9 +18,19 @@ import * as vscode from 'vscode'; import { DebugProtocol } from '@vscode/debugprotocol'; import { AdapterVariableTracker, hexAddress, notADigit } from './adapter-capabilities'; import { toHexStringWithRadixMarker, VariableRange } from '../../common/memory-range'; -import { sendRequest, EvaluateExpression } from '../../common/debug-requests'; +import { sendRequest } from '../../common/debug-requests'; + +export namespace CEvaluateExpression { + export function sizeOf(expression: string): string { + return `sizeof(${expression})`; + } + export function addressOf(expression: string): string { + return `&(${expression})`; + } +}; export class CTracker extends AdapterVariableTracker { + /** * Resolves memory location and size using evaluate requests for `$(variable.name)` and `sizeof(variable.name)` * Ignores the presence or absence of variable.memoryReference. @@ -32,15 +42,14 @@ export class CTracker extends AdapterVariableTracker { return undefined; } try { - const [addressResponse, sizeResponse] = await Promise.all([ - sendRequest(session, 'evaluate', { expression: EvaluateExpression.addressOf(variable.name), context: 'watch', frameId: this.currentFrame }), - sendRequest(session, 'evaluate', { expression: EvaluateExpression.sizeOf(variable.name), context: 'watch', frameId: this.currentFrame }) - ]); - const addressPart = hexAddress.exec(addressResponse.result); - if (!addressPart) { return undefined; } - const startAddress = BigInt(addressPart[0]); - const endAddress = notADigit.test(sizeResponse.result) ? undefined : startAddress + BigInt(sizeResponse.result); - this.logger.debug('Resolved', variable.name, { start: addressPart[0], size: sizeResponse.result }); + const variableAddress = await this.getAddressOfVariable(variable.name, session); + if (!variableAddress) { return undefined; } + const variableSize = await this.getSizeOfVariable(variable.name, session); + if (!variableSize) { return undefined; } + + const startAddress = BigInt(variableAddress); + const endAddress = BigInt(variableAddress) + variableSize; + this.logger.debug('Resolved', variable.name, { start: variableAddress, size: variableSize }); return { name: variable.name, startAddress: toHexStringWithRadixMarker(startAddress), @@ -52,4 +61,15 @@ export class CTracker extends AdapterVariableTracker { return undefined; } } + + async getAddressOfVariable(variableName: string, session: vscode.DebugSession): Promise { + const response = await sendRequest(session, 'evaluate', { expression: CEvaluateExpression.addressOf(variableName), context: 'watch', frameId: this.currentFrame }); + const addressPart = hexAddress.exec(response.result); + return addressPart ? addressPart[0] : undefined; + } + + async getSizeOfVariable(variableName: string, session: vscode.DebugSession): Promise { + const response = await sendRequest(session, 'evaluate', { expression: CEvaluateExpression.sizeOf(variableName), context: 'watch', frameId: this.currentFrame }); + return notADigit.test(response.result) ? undefined : BigInt(response.result); + } } diff --git a/src/plugin/external-views.ts b/src/plugin/external-views.ts new file mode 100644 index 0000000..6c350ba --- /dev/null +++ b/src/plugin/external-views.ts @@ -0,0 +1,32 @@ +/******************************************************************************** + * Copyright (C) 2024 EclipseSource. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { DebugProtocol } from '@vscode/debugprotocol'; +import { isDebugVariable, isDebugScope, isDebugEvaluateArguments } from '../common/debug-requests'; + +export namespace VariablesView { + // from https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/debug/browser/variablesView.ts + export interface IVariablesContext { + sessionId: string | undefined; + container: DebugProtocol.Variable | DebugProtocol.Scope | DebugProtocol.EvaluateArguments; + variable: DebugProtocol.Variable; + } +} + +export function isVariablesContext(context: VariablesView.IVariablesContext | unknown): context is VariablesView.IVariablesContext { + const assumed = context ? context as VariablesView.IVariablesContext : undefined; + return isDebugVariable(assumed?.variable) && (isDebugVariable(assumed?.container) || isDebugScope(assumed?.container) || isDebugEvaluateArguments(assumed?.container)); +} diff --git a/src/plugin/memory-provider.ts b/src/plugin/memory-provider.ts index 12cb3ee..f6c4f34 100644 --- a/src/plugin/memory-provider.ts +++ b/src/plugin/memory-provider.ts @@ -132,14 +132,22 @@ export class MemoryProvider { }); } - public async evaluate(args: DebugProtocol.EvaluateArguments): Promise { - return sendRequest(this.assertActiveSession('evaluate'), 'evaluate', args); - } - public async getVariables(variableArguments: DebugProtocol.ReadMemoryArguments): Promise { const session = this.assertActiveSession('get variables'); const handler = this.adapterRegistry?.getHandlerForSession(session.type); if (handler?.getResidents) { return handler.getResidents(session, variableArguments); } return handler?.getVariables?.(session) ?? []; } + + public async getAddressOfVariable(variableName: string): Promise { + const session = this.assertActiveSession('get address of variable'); + const handler = this.adapterRegistry?.getHandlerForSession(session.type); + return handler?.getAddressOfVariable?.(session, variableName); + } + + public async getSizeOfVariable(variableName: string): Promise { + const session = this.assertActiveSession('get address of variable'); + const handler = this.adapterRegistry?.getHandlerForSession(session.type); + return handler?.getSizeOfVariable?.(session, variableName); + } } diff --git a/src/plugin/memory-storage.ts b/src/plugin/memory-storage.ts index aad73b4..0bb1d33 100644 --- a/src/plugin/memory-storage.ts +++ b/src/plugin/memory-storage.ts @@ -20,13 +20,13 @@ import { URI, Utils } from 'vscode-uri'; import { IntelHEX } from '../common/intel-hex'; import { bytesToStringMemory, createMemoryFromRead, - isMemoryVariableNode, validateCount, validateMemoryReference, validateOffset + validateCount, validateMemoryReference, validateOffset } from '../common/memory'; import { toHexStringWithRadixMarker } from '../common/memory-range'; import * as manifest from './manifest'; import { MemoryProvider } from './memory-provider'; -import { EvaluateExpression } from '../common/debug-requests'; import { ApplyMemoryArguments, ApplyMemoryResult, MemoryOptions, StoreMemoryArguments } from '../common/messaging'; +import { isVariablesContext } from './external-views'; export const StoreCommandType = `${manifest.PACKAGE_NAME}.store-file`; export const ApplyCommandType = `${manifest.PACKAGE_NAME}.apply-file`; @@ -34,10 +34,11 @@ export const ApplyCommandType = `${manifest.PACKAGE_NAME}.apply-file`; const VALID_FILE_NAME_CHARS = /[^a-zA-Z0-9 _-]/g; type StoreMemoryOptions = Required & { + proposedOutputName?: string, outputFile: vscode.Uri; }; -const DEFAULT_STORE_OPTIONS: Omit = { +const DEFAULT_STORE_OPTIONS: Omit = { memoryReference: toHexStringWithRadixMarker(0n, 8), offset: 0, count: 256 @@ -91,12 +92,12 @@ export class MemoryStorage { if (!args) { return {}; } - if (isMemoryVariableNode(args)) { + if (isVariablesContext(args)) { try { const variableName = args.variable.evaluateName ?? args.variable.name; - const { result } = await this.memoryProvider.evaluate({ expression: EvaluateExpression.sizeOf(variableName), context: 'watch' }); - const count = validateCount(result) === undefined ? Number(result) : undefined; - return { count, memoryReference: EvaluateExpression.addressOf(variableName), offset: 0 }; + const count = await this.memoryProvider.getSizeOfVariable(variableName); + const memoryReference = args.variable.memoryReference ?? await this.memoryProvider.getAddressOfVariable(variableName); + return { count: Number(count), memoryReference, offset: 0, proposedOutputName: variableName }; } catch (error) { // ignore, we are just using them as default values return { memoryReference: args.variable.memoryReference, offset: 0 }; @@ -137,7 +138,9 @@ export class MemoryStorage { return; } const workspaceUri = vscode.workspace.workspaceFolders?.[0]?.uri; - const defaultUri = workspaceUri ? Utils.joinPath(workspaceUri, memoryReference.replace(VALID_FILE_NAME_CHARS, '') + '_' + count) : workspaceUri; + const proposedName = providedDefault?.proposedOutputName ?? memoryReference + '_' + count; + const validName = proposedName.replace(VALID_FILE_NAME_CHARS, ''); + const defaultUri = workspaceUri ? Utils.joinPath(workspaceUri, validName) : workspaceUri; const saveFile = await vscode.window.showSaveDialog({ title: 'Store Memory', defaultUri, filters: IntelHEX.DialogFilters }); if (!saveFile) { return; @@ -159,7 +162,7 @@ export class MemoryStorage { let memoryReference: string | undefined; let count: number | undefined; for (const [address, memory] of memoryMap) { - memoryReference = toHexStringWithRadixMarker(BigInt(address)); + memoryReference = toHexStringWithRadixMarker(address); count = memory.length; const data = bytesToStringMemory(memory); await this.memoryProvider.writeMemory({ memoryReference, data, count }); diff --git a/src/plugin/memory-webview-main.ts b/src/plugin/memory-webview-main.ts index a4afee1..2ba2a63 100644 --- a/src/plugin/memory-webview-main.ts +++ b/src/plugin/memory-webview-main.ts @@ -17,7 +17,6 @@ import * as vscode from 'vscode'; import { Messenger } from 'vscode-messenger'; import { WebviewIdMessageParticipant } from 'vscode-messenger-common'; -import { isMemoryVariableNode } from '../common/memory'; import { VariableRange } from '../common/memory-range'; import { MemoryOptions, @@ -44,6 +43,7 @@ import { outputChannelLogger } from './logger'; import * as manifest from './manifest'; import { MemoryProvider } from './memory-provider'; import { ApplyCommandType, StoreCommandType } from './memory-storage'; +import { isVariablesContext } from './external-views'; enum RefreshEnum { off = 0, @@ -80,9 +80,10 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider { context.subscriptions.push( vscode.window.registerCustomEditorProvider(manifest.EDITOR_NAME, this), vscode.commands.registerCommand(MemoryWebview.ShowCommandType, () => this.show()), - vscode.commands.registerCommand(MemoryWebview.VariableCommandType, node => { - if (isMemoryVariableNode(node)) { - this.show({ memoryReference: node.variable.memoryReference.toString() }); + vscode.commands.registerCommand(MemoryWebview.VariableCommandType, async args => { + if (isVariablesContext(args)) { + const memoryReference = args.variable.memoryReference ?? await this.memoryProvider.getAddressOfVariable(args.variable.name); + this.show({ memoryReference }); } }) ); @@ -243,7 +244,7 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider { protected async writeMemory(request: WriteMemoryArguments): Promise { try { - return this.memoryProvider.writeMemory(request); + return await this.memoryProvider.writeMemory(request); } catch (err) { this.logError('Error writing memory', err); } diff --git a/src/webview/components/memory-table.tsx b/src/webview/components/memory-table.tsx index 898d822..f2e8a21 100644 --- a/src/webview/components/memory-table.tsx +++ b/src/webview/components/memory-table.tsx @@ -14,7 +14,6 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { DebugProtocol } from '@vscode/debugprotocol'; import memoize from 'memoize-one'; import { Column } from 'primereact/column'; import { DataTable, DataTableCellSelection, DataTableProps, DataTableSelectionCellChangeEvent } from 'primereact/datatable'; @@ -26,14 +25,14 @@ import isDeepEqual from 'fast-deep-equal'; import { classNames } from 'primereact/utils'; import { tryToNumber } from '../../common/typescript'; import { DataColumn } from '../columns/data-column'; -import { ReadMemoryArguments } from '../../common/messaging'; +import { MemoryOptions, ReadMemoryArguments } from '../../common/messaging'; import { Memory } from '../../common/memory'; export interface MoreMemorySelectProps { - activeReadArguments: Required; + activeReadArguments: Required; options: number[]; direction: 'above' | 'below'; - fetchMemory(partialOptions?: Partial): Promise; + fetchMemory(partialOptions?: MemoryOptions): Promise; disabled: boolean } @@ -124,8 +123,8 @@ export const MoreMemorySelect: React.FC; - activeReadArguments: Required; + configuredReadArguments: Required; + activeReadArguments: Required; memory?: Memory; decorations: Decoration[]; effectiveAddressLength: number; diff --git a/src/webview/components/memory-widget.tsx b/src/webview/components/memory-widget.tsx index da793f4..1ca21cc 100644 --- a/src/webview/components/memory-widget.tsx +++ b/src/webview/components/memory-widget.tsx @@ -14,18 +14,17 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { DebugProtocol } from '@vscode/debugprotocol'; import React from 'react'; import { ColumnStatus } from '../columns/column-contribution-service'; import { Decoration, Endianness, MemoryDisplayConfiguration, MemoryState } from '../utils/view-types'; import { MemoryTable } from './memory-table'; import { OptionsWidget } from './options-widget'; -import { MemoryOptions } from '../../common/messaging'; +import { MemoryOptions, ReadMemoryArguments } from '../../common/messaging'; import { Memory } from '../../common/memory'; interface MemoryWidgetProps extends MemoryDisplayConfiguration { - configuredReadArguments: Required; - activeReadArguments: Required; + configuredReadArguments: Required; + activeReadArguments: Required; memory?: Memory; title: string; decorations: Decoration[]; @@ -40,8 +39,8 @@ interface MemoryWidgetProps extends MemoryDisplayConfiguration { resetMemoryDisplayConfiguration: () => void; updateTitle: (title: string) => void; fetchMemory(partialOptions?: MemoryOptions): Promise; - triggerStoreMemory(): void; - triggerApplyMemory(): void; + storeMemory(): void; + applyMemory(): void; } interface MemoryWidgetState { @@ -80,8 +79,8 @@ export class MemoryWidget extends React.Component void; updateTitle: (title: string) => void; updateMemoryState: (state: Partial) => void; - fetchMemory(partialOptions?: Partial): Promise + fetchMemory(partialOptions?: MemoryOptions): Promise toggleColumn(id: string, isVisible: boolean): void; toggleFrozen: () => void; isFrozen: boolean; - triggerStoreMemory(): void; - triggerApplyMemory(): void; + storeMemory(): void; + applyMemory(): void; } interface OptionsWidgetState { @@ -171,7 +170,7 @@ export class OptionsWidget extends React.Component { return; } try { - // if we are dealing with numeric addresses (and not expressions) then we can determine the overlap + // If we are dealing with numeric addresses (and not expressions) then we can determine the overlap. + // Note that we use big int arithmetic here to determine the overlap for (start address + length) vs (memory state address + length), i.e., + // we do not actually determine the end address may need to consider the size of a word in bytes const written: BigIntMemoryRange = { startAddress: BigInt(writtenMemory.memoryReference), endAddress: BigInt(writtenMemory.memoryReference) + BigInt(writtenMemory.count ?? 0) @@ -174,8 +176,8 @@ class App extends React.Component<{}, MemoryAppState> { addressPadding={this.state.addressPadding} addressRadix={this.state.addressRadix} showRadixPrefix={this.state.showRadixPrefix} - triggerStoreMemory={this.requestStoreMemory} - triggerApplyMemory={this.requestApplyMemory} + storeMemory={this.storeMemory} + applyMemory={this.applyMemory} /> ; } @@ -271,11 +273,11 @@ class App extends React.Component<{}, MemoryAppState> { this.setState(prevState => ({ ...prevState, isFrozen: !prevState.isFrozen })); } - protected requestStoreMemory = (): void => { - messenger.sendRequest(storeMemoryType, HOST_EXTENSION, { ...this.state.activeReadArguments }); + protected storeMemory = async (): Promise => { + await messenger.sendRequest(storeMemoryType, HOST_EXTENSION, { ...this.state.activeReadArguments }); }; - protected requestApplyMemory = async (): Promise => { + protected applyMemory = async (): Promise => { await messenger.sendRequest(applyMemoryType, HOST_EXTENSION, undefined); }; }