Pass entire RenderBatch to JS side in one call
This commit is contained in:
parent
55592f583b
commit
c81d537ea3
|
|
@ -1,5 +1,5 @@
|
|||
import { invokeWithJsonMarshalling } from './InvokeWithJsonMarshalling';
|
||||
import { attachComponentToElement, renderRenderTree } from '../Rendering/Renderer';
|
||||
import { attachComponentToElement, renderBatch } from '../Rendering/Renderer';
|
||||
|
||||
/**
|
||||
* The definitive list of internal functions invokable from .NET code.
|
||||
|
|
@ -8,5 +8,5 @@ import { attachComponentToElement, renderRenderTree } from '../Rendering/Rendere
|
|||
export const internalRegisteredFunctions = {
|
||||
attachComponentToElement,
|
||||
invokeWithJsonMarshalling,
|
||||
renderRenderTree,
|
||||
renderBatch,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -124,6 +124,10 @@ export const monoPlatform: Platform = {
|
|||
const fieldValue = Module.getValue((baseAddress as any as number) + (fieldOffset || 0), 'i32');
|
||||
return fieldValue === 0 ? null : monoPlatform.toJavaScriptString(fieldValue as any as System_String);
|
||||
},
|
||||
|
||||
readStructField: function readStructField(baseAddress: Pointer, fieldOffset?: number): Pointer {
|
||||
return ((baseAddress as any as number) + (fieldOffset || 0)) as any as Pointer;
|
||||
},
|
||||
};
|
||||
|
||||
// Bypass normal type checking to add this extra function. It's only intended to be called from
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
readInt32Field(baseAddress: Pointer, fieldOffset?: number): number;
|
||||
readObjectField(baseAddress: Pointer, fieldOffset?: number): System_Object;
|
||||
readStringField(baseAddress: Pointer, fieldOffset?: number): string | null;
|
||||
readStructField(baseAddress: Pointer, fieldOffset?: number): Pointer;
|
||||
}
|
||||
|
||||
// We don't actually instantiate any of these at runtime. For perf it's preferable to
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
import { Pointer, System_Array } from '../Platform/Platform';
|
||||
import { platform } from '../Environment';
|
||||
|
||||
// Keep in sync with the structs in .NET code
|
||||
|
||||
export const renderBatch = {
|
||||
updatedComponents: (obj: RenderBatchPointer) => platform.readStructField(obj, 0) as ArrayRangePointer,
|
||||
};
|
||||
|
||||
const arrayRangeStructLength = 8;
|
||||
export const arrayRange = {
|
||||
array: (obj: ArrayRangePointer) => platform.readObjectField(obj, 0) as System_Array,
|
||||
count: (obj: ArrayRangePointer) => 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(obj, 4) as ArrayRangePointer,
|
||||
currentState: (obj: RenderTreeDiffPointer) => platform.readStructField(obj, 4 + arrayRangeStructLength) as ArrayRangePointer,
|
||||
};
|
||||
|
||||
// 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 RenderTreeDiffPointer extends Pointer { RenderTreeDiffPointer__DO_NOT_IMPLEMENT: any }
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { Pointer, System_Array } from '../Platform/Platform';
|
||||
import { platform } from '../Environment';
|
||||
|
||||
// Keep in sync with the RenderComponentArgs struct in .NET code
|
||||
export const renderComponentArgs = {
|
||||
browserRendererId: (obj: RenderComponentArgsPointer) => platform.readInt32Field(obj, 0),
|
||||
componentId: (obj: RenderComponentArgsPointer) => platform.readInt32Field(obj, 4),
|
||||
renderTreeEdits: (obj: RenderComponentArgsPointer) => platform.readObjectField(obj, 8) as System_Array,
|
||||
renderTreeEditsLength: (obj: RenderComponentArgsPointer) => platform.readInt32Field(obj, 12),
|
||||
renderTree: (obj: RenderComponentArgsPointer) => platform.readObjectField(obj, 16) as System_Array
|
||||
}
|
||||
|
||||
// Nominal type to ensure only valid pointers are passed to the renderComponentArgs functions.
|
||||
// At runtime the values are just numbers.
|
||||
export interface RenderComponentArgsPointer extends Pointer { RenderComponentArgsPointer__DO_NOT_IMPLEMENT: any }
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
import { platform } from '../Environment';
|
||||
import { getTreeNodePtr, renderTreeNode, NodeType, RenderTreeNodePointer } from './RenderTreeNode';
|
||||
import { RenderTreeEditPointer } from './RenderTreeEdit';
|
||||
import { renderComponentArgs, RenderComponentArgsPointer } from './RenderComponentArgs';
|
||||
import { renderBatch as renderBatchStruct, arrayRange, renderTreeDiffStructLength, renderTreeDiff, RenderBatchPointer, RenderTreeDiffPointer } from './RenderBatch';
|
||||
import { BrowserRenderer } from './BrowserRenderer';
|
||||
|
||||
type BrowserRendererRegistry = { [browserRendererId: number]: BrowserRenderer };
|
||||
|
|
@ -23,19 +23,27 @@ export function attachComponentToElement(browserRendererId: number, elementSelec
|
|||
clearElement(element);
|
||||
}
|
||||
|
||||
export function renderRenderTree(args: RenderComponentArgsPointer) {
|
||||
const browserRendererId = renderComponentArgs.browserRendererId(args);
|
||||
export function renderBatch(browserRendererId: number, batch: RenderBatchPointer) {
|
||||
const browserRenderer = browserRenderers[browserRendererId];
|
||||
if (!browserRenderer) {
|
||||
throw new Error(`There is no browser renderer with ID ${browserRendererId}.`);
|
||||
}
|
||||
|
||||
const updatedComponents = renderBatchStruct.updatedComponents(batch);
|
||||
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 componentId = renderComponentArgs.componentId(args);
|
||||
const edits = renderComponentArgs.renderTreeEdits(args);
|
||||
const editsLength = renderComponentArgs.renderTreeEditsLength(args);
|
||||
const tree = renderComponentArgs.renderTree(args);
|
||||
const editsArrayRange = renderTreeDiff.edits(updatedComponentDiff);
|
||||
const currentStateArrayRange = renderTreeDiff.currentState(updatedComponentDiff);
|
||||
|
||||
browserRenderer.updateComponent(componentId, edits, editsLength, tree);
|
||||
const edits = arrayRange.array(editsArrayRange);
|
||||
const editsLength = arrayRange.count(editsArrayRange);
|
||||
const tree = arrayRange.array(currentStateArrayRange);
|
||||
browserRenderer.updateComponent(componentId, edits, editsLength, tree);
|
||||
}
|
||||
}
|
||||
|
||||
function clearElement(element: Element) {
|
||||
|
|
|
|||
|
|
@ -68,33 +68,10 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
|||
/// <inheritdoc />
|
||||
protected override void UpdateDisplay(RenderBatch batch)
|
||||
{
|
||||
// TODO: Pass to JS in a single call
|
||||
for (var i = 0; i < batch.UpdatedComponents.Count; i++)
|
||||
{
|
||||
ref var diff = ref batch.UpdatedComponents.Array[i];
|
||||
RegisteredFunction.InvokeUnmarshalled<RenderComponentArgs, object>(
|
||||
"renderRenderTree",
|
||||
new RenderComponentArgs
|
||||
{
|
||||
BrowserRendererId = _browserRendererId,
|
||||
ComponentId = diff.ComponentId,
|
||||
RenderTreeEdits = diff.Edits.Array,
|
||||
RenderTreeEditsLength = diff.Edits.Count,
|
||||
RenderTree = diff.CurrentState.Array
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Encapsulates the data we pass to the JS rendering function
|
||||
private struct RenderComponentArgs
|
||||
{
|
||||
// Important: If you edit this struct, keep it in sync with RenderComponentArgs.ts
|
||||
|
||||
public int BrowserRendererId;
|
||||
public int ComponentId;
|
||||
public RenderTreeEdit[] RenderTreeEdits;
|
||||
public int RenderTreeEditsLength;
|
||||
public RenderTreeNode[] RenderTree;
|
||||
RegisteredFunction.InvokeUnmarshalled<int, RenderBatch, object>(
|
||||
"renderBatch",
|
||||
_browserRendererId,
|
||||
batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue