Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions etc/runtime.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,8 @@ interface RuntimeContext extends LegacyCompatibleRuntimeContext {
// (undocumented)
ctxStore: DataStore<"CTX">;
// (undocumented)
eventMap?: Map<string, Event>;
// (undocumented)
forEachIndex?: number;
// (undocumented)
forEachItem?: unknown;
Expand Down
33 changes: 30 additions & 3 deletions packages/runtime/src/internal/bindListeners.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1120,21 +1120,40 @@ describe("listenerFactory for useProvider", () => {
test("useProvider with callback", async () => {
const brick = {
element: {
callbackSuccess: jest.fn(),
callbackSuccess: jest.fn((_a: unknown, _b: unknown) =>
Promise.resolve("callback success")
),
callbackError: jest.fn(),
callbackFinally: jest.fn(),
deepCallback: jest.fn(),
},
};
listenerFactory(
{
key: "initialEvent",
useProvider: "my-timeout-provider",
method: "willBeReplacedByResolve" as "resolve",
args: [100, "resolved"],
callback: {
success: {
key: "timeoutEvent",
target: "_self",
method: "callbackSuccess",
args: ["<% EVENT.detail %>"],
args: [
"<% EVENT_BY_KEY.timeoutEvent.detail %>",
"<% EVENT_BY_KEY.initialEvent.detail %>",
],
callback: {
success: {
target: "_self",
method: "deepCallback",
args: [
"<% EVENT.detail %>",
"<% EVENT_BY_KEY.timeoutEvent.detail %>",
"<% EVENT_BY_KEY.initialEvent.detail %>",
],
},
},
},
error: {
target: "_self",
Expand All @@ -1159,9 +1178,17 @@ describe("listenerFactory for useProvider", () => {
await new Promise((resolve) => setTimeout(resolve, 0));
expect(myTimeoutProvider).toHaveBeenCalledTimes(1);
await new Promise((resolve) => setTimeout(resolve, 100));
expect(brick.element.callbackSuccess).toHaveBeenCalledWith("resolved");
expect(brick.element.callbackSuccess).toHaveBeenCalledWith(
"resolved",
"ok"
);
expect(brick.element.callbackError).not.toHaveBeenCalled();
expect(brick.element.callbackFinally).toHaveBeenCalledWith(null);
expect(brick.element.deepCallback).toHaveBeenCalledWith(
"callback success",
"resolved",
"ok"
);
});

test("useProvider without args", async () => {
Expand Down
13 changes: 12 additions & 1 deletion packages/runtime/src/internal/bindListeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,22 @@ export function isConditionalEventHandler(

export function listenerFactory(
handlers: BrickEventHandler | BrickEventHandler[],
runtimeContext: RuntimeContext,
_runtimeContext: RuntimeContext,
runtimeBrick?: ElementHolder
) {
return function (event: Event): void {
for (const handler of ([] as BrickEventHandler[]).concat(handlers)) {
let runtimeContext = _runtimeContext;
if (handler.key && typeof handler.key === "string") {
runtimeContext = {
..._runtimeContext,
eventMap: new Map([
...(_runtimeContext.eventMap || []),
[handler.key, event],
]),
};
}

if (!checkIf(handler, { ...runtimeContext, event })) {
if (handler.else) {
listenerFactory(handler.else, runtimeContext, runtimeBrick)(event);
Expand Down
16 changes: 15 additions & 1 deletion packages/runtime/src/internal/compute/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ function lowLevelEvaluate(
options.lazy ||
(attemptToVisitGlobals.has("EVENT") &&
!hasOwnProperty(runtimeContext, "event")) ||
(attemptToVisitGlobals.has("EVENT_BY_KEY") &&
!hasOwnProperty(runtimeContext, "eventMap")) ||
(attemptToVisitGlobals.has("DATA") &&
!hasOwnProperty(runtimeContext, "data"))
) {
Expand Down Expand Up @@ -303,7 +305,8 @@ function lowLevelEvaluate(
return {
blockingList,
run() {
const { ctxStore, data, event, unsafe_penetrate } = runtimeContext;
const { ctxStore, data, event, eventMap, unsafe_penetrate } =
runtimeContext;

const penetrableCtx = unsafe_penetrate
? _internalApiGetRuntimeContext()!
Expand Down Expand Up @@ -360,6 +363,17 @@ function lowLevelEvaluate(
case "EVENT":
globalVariables[variableName] = event;
break;
case "EVENT_BY_KEY":
globalVariables[variableName] = getDynamicReadOnlyProxy({
get(_target, key) {
return eventMap?.get(key as string);
},
// istanbul ignore next: dev only
ownKeys() {
return Array.from(eventMap?.keys() ?? []);
},
});
break;
case "FLAGS":
globalVariables[variableName] = getReadOnlyProxy(flags);
break;
Expand Down
1 change: 1 addition & 0 deletions packages/runtime/src/internal/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface RuntimeContext extends LegacyCompatibleRuntimeContext {
forEachSize?: number;
appendI18nNamespace?: string;
isolatedRoot?: symbol;
eventMap?: Map<string, Event>;

formStateStoreMap: Map<string, DataStore<"FORM_STATE">>;
formStateStoreId?: string;
Expand Down
14 changes: 14 additions & 0 deletions packages/types/src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,12 @@ export interface BuiltinBrickEventHandler {

/** {@inheritDoc ConditionalEventHandler.else} */
else?: BrickEventHandler | BrickEventHandler[];

/**
* 设置事件对象的 key 名,在处理器和回调中可以通过 `EVENT_BY_KEY.<key>` 来访问该事件对象。
* 主要用于在嵌套的多个层级的事件回调中引用指定的事件对象。
*/
key?: string;
}

/**
Expand Down Expand Up @@ -1069,6 +1075,9 @@ export interface UseProviderEventHandler

/** {@inheritDoc ConditionalEventHandler.else} */
else?: BrickEventHandler | BrickEventHandler[];

/** {@inheritDoc BuiltinBrickEventHandler.key} */
key?: string;
}

/**
Expand Down Expand Up @@ -1151,6 +1160,9 @@ export interface BaseCustomBrickEventHandler {

/** {@inheritDoc ConditionalEventHandler.else} */
else?: BrickEventHandler | BrickEventHandler[];

/** {@inheritDoc BuiltinBrickEventHandler.key} */
key?: string;
}

/*
Expand All @@ -1163,6 +1175,8 @@ export interface ConditionalEventHandler {
then: BrickEventHandler | BrickEventHandler[];
/** 不满足条件分支 */
else?: BrickEventHandler | BrickEventHandler[];
/** {@inheritDoc BuiltinBrickEventHandler.key} */
key?: string;
}

/**
Expand Down
Loading