Improve naming for direct memory access APIs in Platform interface

This commit is contained in:
Steve Sanderson 2018-01-10 12:15:26 +00:00
parent 0187384638
commit 950250d1f7
4 changed files with 32 additions and 40 deletions

View File

@ -107,17 +107,22 @@ export const monoPlatform: Platform = {
return address as any as Pointer;
},
getHeapObjectFieldsPtr: function getHeapObjectFieldsPtr(heapObject: System_Object): Pointer {
getObjectFieldsBaseAddress: function getObjectFieldsBaseAddress(referenceTypedObject: System_Object): Pointer {
// The first two int32 values are internal Mono data
return (heapObject as any as number + 8) as any as Pointer;
return (referenceTypedObject as any as number + 8) as any as Pointer;
},
readHeapInt32: function readHeapInt32(address: Pointer, offset?: number): number {
return Module.getValue((address as any as number) + (offset || 0), 'i32');
readInt32Field: function readHeapInt32(baseAddress: Pointer, fieldOffset?: number): number {
return Module.getValue((baseAddress as any as number) + (fieldOffset || 0), 'i32');
},
readHeapObject: function readHeapObject(address: Pointer, offset?: number): System_Object {
return monoPlatform.readHeapInt32(address, offset) as any as System_Object;
readObjectField: function readHeapObject(baseAddress: Pointer, fieldOffset?: number): System_Object {
return Module.getValue((baseAddress as any as number) + (fieldOffset || 0), 'i32') as any as System_Object;
},
readStringField: function readHeapObject(baseAddress: Pointer, fieldOffset?: number): string | null {
const fieldValue = Module.getValue((baseAddress as any as number) + (fieldOffset || 0), 'i32');
return fieldValue === 0 ? null : monoPlatform.toJavaScriptString(fieldValue as any as System_String);
},
};

View File

@ -11,10 +11,10 @@
getArrayLength(array: System_Array): number;
getArrayEntryPtr(array: System_Array, index: number, itemSize: number): Pointer;
getHeapObjectFieldsPtr(heapObject: System_Object): Pointer;
readHeapInt32(address: Pointer, offset?: number): number;
readHeapObject(address: Pointer, offset?: number): System_Object;
getObjectFieldsBaseAddress(referenceTypedObject: System_Object): Pointer;
readInt32Field(baseAddress: Pointer, fieldOffset?: number): number;
readObjectField(baseAddress: Pointer, fieldOffset?: number): System_Object;
readStringField(baseAddress: Pointer, fieldOffset?: number): string | null;
}
// We don't actually instantiate any of these at runtime. For perf it's preferable to

View File

@ -12,15 +12,15 @@ export function getTreeNodePtr(renderTreeEntries: System_Array, index: number):
export const renderTreeNode = {
// The properties and memory layout must be kept in sync with the .NET equivalent in RenderTreeNode.cs
nodeType: (node: RenderTreeNodePointer) => _readInt32Property(node, 0) as NodeType,
elementName: (node: RenderTreeNodePointer) => _readStringProperty(node, 4),
descendantsEndIndex: (node: RenderTreeNodePointer) => _readInt32Property(node, 8) as NodeType,
textContent: (node: RenderTreeNodePointer) => _readStringProperty(node, 12),
attributeName: (node: RenderTreeNodePointer) => _readStringProperty(node, 16),
attributeValue: (node: RenderTreeNodePointer) => _readStringProperty(node, 20),
attributeEventHandlerValue: (node: RenderTreeNodePointer) => _readObjectProperty(node, 24),
componentId: (node: RenderTreeNodePointer) => _readInt32Property(node, 28),
component: (node: RenderTreeNodePointer) => _readObjectProperty(node, 32),
nodeType: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 0) as NodeType,
elementName: (node: RenderTreeNodePointer) => platform.readStringField(node, 4),
descendantsEndIndex: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 8) as NodeType,
textContent: (node: RenderTreeNodePointer) => platform.readStringField(node, 12),
attributeName: (node: RenderTreeNodePointer) => platform.readStringField(node, 16),
attributeValue: (node: RenderTreeNodePointer) => platform.readStringField(node, 20),
attributeEventHandlerValue: (node: RenderTreeNodePointer) => platform.readObjectField(node, 24),
componentId: (node: RenderTreeNodePointer) => platform.readInt32Field(node, 28),
component: (node: RenderTreeNodePointer) => platform.readObjectField(node, 32),
};
export enum NodeType {
@ -31,19 +31,6 @@ export enum NodeType {
component = 4,
}
function _readInt32Property(baseAddress: Pointer, offsetBytes: number) {
return platform.readHeapInt32(baseAddress, offsetBytes);
}
function _readObjectProperty(baseAddress: Pointer, offsetBytes: number) {
return platform.readHeapObject(baseAddress, offsetBytes);
}
function _readStringProperty(baseAddress: Pointer, offsetBytes: number) {
var managedString = platform.readHeapObject(baseAddress, offsetBytes) as System_String;
return platform.toJavaScriptString(managedString);
}
// Nominal type to ensure only valid pointers are passed to the renderTreeNode functions.
// At runtime the values are just numbers.
export interface RenderTreeNodePointer extends Pointer { RenderTreeNodePointer__DO_NOT_IMPLEMENT: any }

View File

@ -25,13 +25,13 @@ export function attachComponentToElement(browserRendererId: number, elementSelec
}
export function renderRenderTree(renderComponentArgs: Pointer) {
const browserRendererId = platform.readHeapInt32(renderComponentArgs, 0);
const browserRendererId = platform.readInt32Field(renderComponentArgs, 0);
const browserRenderer = browserRenderers[browserRendererId];
if (!browserRenderer) {
throw new Error(`There is no browser renderer with ID ${browserRendererId}.`);
}
const componentId = platform.readHeapInt32(renderComponentArgs, 4);
const componentId = platform.readInt32Field(renderComponentArgs, 4);
const element = browserRenderer[componentId];
if (!element) {
throw new Error(`No element is currently associated with component ${componentId}`);
@ -39,8 +39,8 @@ export function renderRenderTree(renderComponentArgs: Pointer) {
clearElement(element);
const tree = platform.readHeapObject(renderComponentArgs, 8) as System_Array;
const treeLength = platform.readHeapInt32(renderComponentArgs, 12);
const tree = platform.readObjectField(renderComponentArgs, 8) as System_Array;
const treeLength = platform.readInt32Field(renderComponentArgs, 12);
insertNodeRange(browserRendererId, componentId, element, tree, 0, treeLength - 1);
}
@ -97,7 +97,7 @@ function insertComponent(browserRendererId: number, intoDomElement: Element, nod
}
function insertElement(browserRendererId: number, componentId: number, intoDomElement: Element, tree: System_Array, elementNode: RenderTreeNodePointer, elementNodeIndex: number) {
const tagName = renderTreeNode.elementName(elementNode);
const tagName = renderTreeNode.elementName(elementNode)!;
const newDomElement = document.createElement(tagName);
intoDomElement.appendChild(newDomElement);
@ -117,7 +117,7 @@ function insertElement(browserRendererId: number, componentId: number, intoDomEl
}
function applyAttribute(browserRendererId: number, componentId: number, toDomElement: Element, attributeNode: RenderTreeNodePointer, attributeNodeIndex: number) {
const attributeName = renderTreeNode.attributeName(attributeNode);
const attributeName = renderTreeNode.attributeName(attributeNode)!;
switch (attributeName) {
case 'onclick':
@ -136,7 +136,7 @@ function applyAttribute(browserRendererId: number, componentId: number, toDomEle
// Treat as a regular string-valued attribute
toDomElement.setAttribute(
attributeName,
renderTreeNode.attributeValue(attributeNode)
renderTreeNode.attributeValue(attributeNode)!
);
break;
}
@ -163,7 +163,7 @@ function raiseEvent(browserRendererId: number, componentId: number, renderTreeNo
}
function insertText(intoDomElement: Element, textNode: RenderTreeNodePointer) {
const textContent = renderTreeNode.textContent(textNode);
const textContent = renderTreeNode.textContent(textNode)!;
const newDomTextNode = document.createTextNode(textContent);
intoDomElement.appendChild(newDomTextNode);
}