In TypeScript, regard System_Array type as generic, even though the type param refers to the entry pointer type, not the element type

This commit is contained in:
Steve Sanderson 2018-01-29 22:07:16 +00:00
parent 855d93ce67
commit 8839a6c558
7 changed files with 29 additions and 27 deletions

View File

@ -97,14 +97,14 @@ export const monoPlatform: Platform = {
return mono_string(jsString);
},
getArrayLength: function getArrayLength(array: System_Array): number {
getArrayLength: function getArrayLength(array: System_Array<any>): number {
return Module.getValue(getArrayDataPointer(array), 'i32');
},
getArrayEntryPtr: function getArrayEntryPtr(array: System_Array, index: number, itemSize: number): Pointer {
getArrayEntryPtr: function getArrayEntryPtr<TPtr extends Pointer>(array: System_Array<TPtr>, index: number, itemSize: number): TPtr {
// First byte is array length, followed by entries
const address = getArrayDataPointer(array) + 4 + index * itemSize;
return address as any as Pointer;
return address as any as TPtr;
},
getObjectFieldsBaseAddress: function getObjectFieldsBaseAddress(referenceTypedObject: System_Object): Pointer {
@ -201,6 +201,6 @@ function asyncLoad(url, onload, onerror) {
xhr.send(null);
}
function getArrayDataPointer(array: System_Array): number {
function getArrayDataPointer<T>(array: System_Array<T>): number {
return <number><any>array + 12; // First byte from here is length, then following bytes are entries
}

View File

@ -8,8 +8,8 @@
toJavaScriptString(dotNetString: System_String): string;
toDotNetString(javaScriptString: string): System_String;
getArrayLength(array: System_Array): number;
getArrayEntryPtr(array: System_Array, index: number, itemSize: number): Pointer;
getArrayLength(array: System_Array<any>): number;
getArrayEntryPtr<TPtr extends Pointer>(array: System_Array<TPtr>, index: number, itemSize: number): TPtr;
getObjectFieldsBaseAddress(referenceTypedObject: System_Object): Pointer;
readInt32Field(baseAddress: Pointer, fieldOffset?: number): number;
@ -24,5 +24,5 @@
export interface MethodHandle { MethodHandle__DO_NOT_IMPLEMENT: any };
export interface System_Object { System_Object__DO_NOT_IMPLEMENT: any };
export interface System_String extends System_Object { System_String__DO_NOT_IMPLEMENT: any }
export interface System_Array extends System_Object { System_Array__DO_NOT_IMPLEMENT: any }
export interface System_Array<T> extends System_Object { System_Array__DO_NOT_IMPLEMENT: any }
export interface Pointer { Pointer__DO_NOT_IMPLEMENT: any }

View File

@ -1,5 +1,5 @@
import { System_Array, MethodHandle } from '../Platform/Platform';
import { getRenderTreeEditPtr, renderTreeEdit, EditType } from './RenderTreeEdit';
import { getRenderTreeEditPtr, renderTreeEdit, RenderTreeEditPointer, EditType } from './RenderTreeEdit';
import { getTreeNodePtr, renderTreeNode, NodeType, RenderTreeNodePointer } from './RenderTreeNode';
import { platform } from '../Environment';
let raiseEventMethod: MethodHandle;
@ -18,7 +18,7 @@ export class BrowserRenderer {
this.childComponentLocations[componentId] = element;
}
public updateComponent(componentId: number, edits: System_Array, editsLength: number, referenceTree: System_Array) {
public updateComponent(componentId: number, edits: System_Array<RenderTreeEditPointer>, editsLength: number, referenceTree: System_Array<RenderTreeNodePointer>) {
const element = this.childComponentLocations[componentId];
if (!element) {
throw new Error(`No element is currently associated with component ${componentId}`);
@ -27,7 +27,7 @@ export class BrowserRenderer {
this.applyEdits(componentId, element, 0, edits, editsLength, referenceTree);
}
applyEdits(componentId: number, parent: Element, childIndex: number, edits: System_Array, editsLength: number, referenceTree: System_Array) {
applyEdits(componentId: number, parent: Element, childIndex: number, edits: System_Array<RenderTreeEditPointer>, editsLength: number, referenceTree: System_Array<RenderTreeNodePointer>) {
let currentDepth = 0;
let childIndexAtCurrentDepth = childIndex;
for (let editIndex = 0; editIndex < editsLength; editIndex++) {
@ -88,7 +88,7 @@ export class BrowserRenderer {
}
}
insertNode(componentId: number, parent: Element, childIndex: number, nodes: System_Array, node: RenderTreeNodePointer, nodeIndex: number) {
insertNode(componentId: number, parent: Element, childIndex: number, nodes: System_Array<RenderTreeNodePointer>, node: RenderTreeNodePointer, nodeIndex: number) {
const nodeType = renderTreeNode.nodeType(node);
switch (nodeType) {
case NodeType.element:
@ -108,7 +108,7 @@ export class BrowserRenderer {
}
}
insertElement(componentId: number, parent: Element, childIndex: number, nodes: System_Array, node: RenderTreeNodePointer, nodeIndex: number) {
insertElement(componentId: number, parent: Element, childIndex: number, nodes: System_Array<RenderTreeNodePointer>, node: RenderTreeNodePointer, nodeIndex: number) {
const tagName = renderTreeNode.elementName(node)!;
const newDomElement = document.createElement(tagName);
insertNodeIntoDOM(newDomElement, parent, childIndex);
@ -196,7 +196,7 @@ export class BrowserRenderer {
}
}
insertNodeRange(componentId: number, parent: Element, childIndex: number, nodes: System_Array, startIndex: number, endIndex: number) {
insertNodeRange(componentId: number, parent: Element, childIndex: number, nodes: System_Array<RenderTreeNodePointer>, startIndex: number, endIndex: number) {
for (let index = startIndex; index <= endIndex; index++) {
const node = getTreeNodePtr(nodes, index);
this.insertNode(componentId, parent, childIndex, nodes, node, index);

View File

@ -1,27 +1,29 @@
import { Pointer, System_Array } from '../Platform/Platform';
import { platform } from '../Environment';
import { RenderTreeNodePointer } from './RenderTreeNode';
import { RenderTreeEditPointer } from './RenderTreeEdit';
// Keep in sync with the structs in .NET code
export const renderBatch = {
updatedComponents: (obj: RenderBatchPointer) => platform.readStructField<ArrayRangePointer>(obj, 0),
updatedComponents: (obj: RenderBatchPointer) => platform.readStructField<ArrayRangePointer<RenderTreeDiffPointer>>(obj, 0),
};
const arrayRangeStructLength = 8;
export const arrayRange = {
array: (obj: ArrayRangePointer) => platform.readObjectField<System_Array>(obj, 0),
count: (obj: ArrayRangePointer) => platform.readInt32Field(obj, 4),
array: <T>(obj: ArrayRangePointer<T>) => platform.readObjectField<System_Array<T>>(obj, 0),
count: <T>(obj: ArrayRangePointer<T>) => platform.readInt32Field(obj, 4),
};
export const renderTreeDiffStructLength = 4 + 2 * arrayRangeStructLength;
export const renderTreeDiff = {
componentId: (obj: RenderTreeDiffPointer) => platform.readInt32Field(obj, 0),
edits: (obj: RenderTreeDiffPointer) => platform.readStructField<ArrayRangePointer>(obj, 4),
currentState: (obj: RenderTreeDiffPointer) => platform.readStructField<ArrayRangePointer>(obj, 4 + arrayRangeStructLength),
edits: (obj: RenderTreeDiffPointer) => platform.readStructField<ArrayRangePointer<RenderTreeEditPointer>>(obj, 4),
currentState: (obj: RenderTreeDiffPointer) => platform.readStructField<ArrayRangePointer<RenderTreeNodePointer>>(obj, 4 + arrayRangeStructLength),
};
// Nominal types to ensure only valid pointers are passed to the functions above.
// At runtime the values are just numbers.
export interface RenderBatchPointer extends Pointer { RenderBatchPointer__DO_NOT_IMPLEMENT: any }
export interface ArrayRangePointer extends Pointer { ArrayRangePointer__DO_NOT_IMPLEMENT: any }
export interface ArrayRangePointer<T> extends Pointer { ArrayRangePointer__DO_NOT_IMPLEMENT: any }
export interface RenderTreeDiffPointer extends Pointer { RenderTreeDiffPointer__DO_NOT_IMPLEMENT: any }

View File

@ -2,8 +2,8 @@
import { platform } from '../Environment';
const renderTreeEditStructLength = 16;
export function getRenderTreeEditPtr(renderTreeEdits: System_Array, index: number): RenderTreeEditPointer {
return platform.getArrayEntryPtr(renderTreeEdits, index, renderTreeEditStructLength) as RenderTreeEditPointer;
export function getRenderTreeEditPtr(renderTreeEdits: System_Array<RenderTreeEditPointer>, index: number) {
return platform.getArrayEntryPtr(renderTreeEdits, index, renderTreeEditStructLength);
}
export const renderTreeEdit = {

View File

@ -6,8 +6,8 @@ const renderTreeNodeStructLength = 40;
// we work in terms of pointers to the structs on the .NET heap, and use static functions that
// know how to read property values from those structs.
export function getTreeNodePtr(renderTreeEntries: System_Array, index: number): RenderTreeNodePointer {
return platform.getArrayEntryPtr(renderTreeEntries, index, renderTreeNodeStructLength) as RenderTreeNodePointer;
export function getTreeNodePtr(renderTreeEntries: System_Array<RenderTreeNodePointer>, index: number) {
return platform.getArrayEntryPtr(renderTreeEntries, index, renderTreeNodeStructLength);
}
export const renderTreeNode = {

View File

@ -33,11 +33,11 @@ export function renderBatch(browserRendererId: number, batch: RenderBatchPointer
const updatedComponentsLength = arrayRange.count(updatedComponents);
const updatedComponentsArray = arrayRange.array(updatedComponents);
for (var i = 0; i < updatedComponentsLength; i++) {
const updatedComponentDiff = platform.getArrayEntryPtr(updatedComponentsArray, i, renderTreeDiffStructLength) as RenderTreeDiffPointer;
const componentId = renderTreeDiff.componentId(updatedComponentDiff);
const diff = platform.getArrayEntryPtr(updatedComponentsArray, i, renderTreeDiffStructLength);
const componentId = renderTreeDiff.componentId(diff);
const editsArrayRange = renderTreeDiff.edits(updatedComponentDiff);
const currentStateArrayRange = renderTreeDiff.currentState(updatedComponentDiff);
const editsArrayRange = renderTreeDiff.edits(diff);
const currentStateArrayRange = renderTreeDiff.currentState(diff);
const edits = arrayRange.array(editsArrayRange);
const editsLength = arrayRange.count(editsArrayRange);