Skip to content

Commit 0aeed99

Browse files
committed
feat(): support accessing specific event object in nested event callbacks
1 parent 468441d commit 0aeed99

File tree

6 files changed

+73
-5
lines changed

6 files changed

+73
-5
lines changed

etc/runtime.api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ interface RuntimeContext extends LegacyCompatibleRuntimeContext {
448448
// (undocumented)
449449
ctxStore: DataStore<"CTX">;
450450
// (undocumented)
451+
eventMap?: Map<string, Event>;
452+
// (undocumented)
451453
forEachIndex?: number;
452454
// (undocumented)
453455
forEachItem?: unknown;

packages/runtime/src/internal/bindListeners.spec.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,21 +1120,40 @@ describe("listenerFactory for useProvider", () => {
11201120
test("useProvider with callback", async () => {
11211121
const brick = {
11221122
element: {
1123-
callbackSuccess: jest.fn(),
1123+
callbackSuccess: jest.fn((_a: unknown, _b: unknown) =>
1124+
Promise.resolve("callback success")
1125+
),
11241126
callbackError: jest.fn(),
11251127
callbackFinally: jest.fn(),
1128+
deepCallback: jest.fn(),
11261129
},
11271130
};
11281131
listenerFactory(
11291132
{
1133+
key: "initialEvent",
11301134
useProvider: "my-timeout-provider",
11311135
method: "willBeReplacedByResolve" as "resolve",
11321136
args: [100, "resolved"],
11331137
callback: {
11341138
success: {
1139+
key: "timeoutEvent",
11351140
target: "_self",
11361141
method: "callbackSuccess",
1137-
args: ["<% EVENT.detail %>"],
1142+
args: [
1143+
"<% EVENT_BY_KEY.timeoutEvent.detail %>",
1144+
"<% EVENT_BY_KEY.initialEvent.detail %>",
1145+
],
1146+
callback: {
1147+
success: {
1148+
target: "_self",
1149+
method: "deepCallback",
1150+
args: [
1151+
"<% EVENT.detail %>",
1152+
"<% EVENT_BY_KEY.timeoutEvent.detail %>",
1153+
"<% EVENT_BY_KEY.initialEvent.detail %>",
1154+
],
1155+
},
1156+
},
11381157
},
11391158
error: {
11401159
target: "_self",
@@ -1159,9 +1178,17 @@ describe("listenerFactory for useProvider", () => {
11591178
await new Promise((resolve) => setTimeout(resolve, 0));
11601179
expect(myTimeoutProvider).toHaveBeenCalledTimes(1);
11611180
await new Promise((resolve) => setTimeout(resolve, 100));
1162-
expect(brick.element.callbackSuccess).toHaveBeenCalledWith("resolved");
1181+
expect(brick.element.callbackSuccess).toHaveBeenCalledWith(
1182+
"resolved",
1183+
"ok"
1184+
);
11631185
expect(brick.element.callbackError).not.toHaveBeenCalled();
11641186
expect(brick.element.callbackFinally).toHaveBeenCalledWith(null);
1187+
expect(brick.element.deepCallback).toHaveBeenCalledWith(
1188+
"callback success",
1189+
"resolved",
1190+
"ok"
1191+
);
11651192
});
11661193

11671194
test("useProvider without args", async () => {

packages/runtime/src/internal/bindListeners.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,22 @@ export function isConditionalEventHandler(
123123

124124
export function listenerFactory(
125125
handlers: BrickEventHandler | BrickEventHandler[],
126-
runtimeContext: RuntimeContext,
126+
_runtimeContext: RuntimeContext,
127127
runtimeBrick?: ElementHolder
128128
) {
129129
return function (event: Event): void {
130130
for (const handler of ([] as BrickEventHandler[]).concat(handlers)) {
131+
let runtimeContext = _runtimeContext;
132+
if (handler.key && typeof handler.key === "string") {
133+
runtimeContext = {
134+
..._runtimeContext,
135+
eventMap: new Map([
136+
...(_runtimeContext.eventMap || []),
137+
[handler.key, event],
138+
]),
139+
};
140+
}
141+
131142
if (!checkIf(handler, { ...runtimeContext, event })) {
132143
if (handler.else) {
133144
listenerFactory(handler.else, runtimeContext, runtimeBrick)(event);

packages/runtime/src/internal/compute/evaluate.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ function lowLevelEvaluate(
189189
options.lazy ||
190190
(attemptToVisitGlobals.has("EVENT") &&
191191
!hasOwnProperty(runtimeContext, "event")) ||
192+
(attemptToVisitGlobals.has("EVENT_BY_KEY") &&
193+
!hasOwnProperty(runtimeContext, "eventMap")) ||
192194
(attemptToVisitGlobals.has("DATA") &&
193195
!hasOwnProperty(runtimeContext, "data"))
194196
) {
@@ -303,7 +305,8 @@ function lowLevelEvaluate(
303305
return {
304306
blockingList,
305307
run() {
306-
const { ctxStore, data, event, unsafe_penetrate } = runtimeContext;
308+
const { ctxStore, data, event, eventMap, unsafe_penetrate } =
309+
runtimeContext;
307310

308311
const penetrableCtx = unsafe_penetrate
309312
? _internalApiGetRuntimeContext()!
@@ -360,6 +363,16 @@ function lowLevelEvaluate(
360363
case "EVENT":
361364
globalVariables[variableName] = event;
362365
break;
366+
case "EVENT_BY_KEY":
367+
globalVariables[variableName] = getDynamicReadOnlyProxy({
368+
get(_target, key) {
369+
return eventMap?.get(key as string);
370+
},
371+
ownKeys() {
372+
return Array.from(eventMap?.keys() ?? []);
373+
},
374+
});
375+
break;
363376
case "FLAGS":
364377
globalVariables[variableName] = getReadOnlyProxy(flags);
365378
break;

packages/runtime/src/internal/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface RuntimeContext extends LegacyCompatibleRuntimeContext {
3131
forEachSize?: number;
3232
appendI18nNamespace?: string;
3333
isolatedRoot?: symbol;
34+
eventMap?: Map<string, Event>;
3435

3536
formStateStoreMap: Map<string, DataStore<"FORM_STATE">>;
3637
formStateStoreId?: string;

packages/types/src/manifest.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,12 @@ export interface BuiltinBrickEventHandler {
10401040

10411041
/** {@inheritDoc ConditionalEventHandler.else} */
10421042
else?: BrickEventHandler | BrickEventHandler[];
1043+
1044+
/**
1045+
* 设置事件对象的 key 名,在处理器和回调中可以通过 `EVENT_BY_KEY.<key>` 来访问该事件对象。
1046+
* 主要用于在嵌套的多个层级的事件回调中引用指定的事件对象。
1047+
*/
1048+
key?: string;
10431049
}
10441050

10451051
/**
@@ -1069,6 +1075,9 @@ export interface UseProviderEventHandler
10691075

10701076
/** {@inheritDoc ConditionalEventHandler.else} */
10711077
else?: BrickEventHandler | BrickEventHandler[];
1078+
1079+
/** {@inheritDoc BuiltinBrickEventHandler.key} */
1080+
key?: string;
10721081
}
10731082

10741083
/**
@@ -1151,6 +1160,9 @@ export interface BaseCustomBrickEventHandler {
11511160

11521161
/** {@inheritDoc ConditionalEventHandler.else} */
11531162
else?: BrickEventHandler | BrickEventHandler[];
1163+
1164+
/** {@inheritDoc BuiltinBrickEventHandler.key} */
1165+
key?: string;
11541166
}
11551167

11561168
/*
@@ -1163,6 +1175,8 @@ export interface ConditionalEventHandler {
11631175
then: BrickEventHandler | BrickEventHandler[];
11641176
/** 不满足条件分支 */
11651177
else?: BrickEventHandler | BrickEventHandler[];
1178+
/** {@inheritDoc BuiltinBrickEventHandler.key} */
1179+
key?: string;
11661180
}
11671181

11681182
/**

0 commit comments

Comments
 (0)