Skip to content

Commit 5514262

Browse files
author
cod1k
committed
Refactor copyExecutionContext for type safety and clarity
Updated the `OverridesStore` type to strictly associate keys with context-specific methods, improving type safety. Renamed and enhanced the descriptor creation function to better handle method overriding and added checks for function-only properties.
1 parent 19db478 commit 5514262

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

packages/cloudflare/src/utils/copyExecutionContext.ts

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type DurableObjectState, type ExecutionContext } from '@cloudflare/workers-types';
22

33
type ContextType = ExecutionContext | DurableObjectState;
4-
type OverridesStore = Map<string | symbol, (...args: unknown[]) => unknown>;
4+
type OverridesStore<T extends ContextType> = Map<keyof T, (...args: unknown[]) => unknown>;
55

66
/**
77
* Creates a new copy of the given execution context, optionally overriding methods.
@@ -12,34 +12,43 @@ type OverridesStore = Map<string | symbol, (...args: unknown[]) => unknown>;
1212
export function copyExecutionContext<T extends ContextType>(ctx: T): T {
1313
if (!ctx) return ctx;
1414

15-
const overrides: OverridesStore = new Map();
15+
const overrides: OverridesStore<T> = new Map();
1616
const contextPrototype = Object.getPrototypeOf(ctx);
17-
const descriptors = Object.getOwnPropertyNames(contextPrototype).reduce((prevDescriptors, methodName) => {
17+
const methodNames = Object.getOwnPropertyNames(contextPrototype) as unknown as (keyof T)[];
18+
const descriptors = methodNames.reduce((prevDescriptors, methodName) => {
1819
if (methodName === 'constructor') return prevDescriptors;
19-
const pd = makeMethodDescriptor(overrides, ctx, methodName as keyof ContextType);
20+
if (typeof ctx[methodName] !== 'function') return prevDescriptors;
21+
const overridableDescriptor = makeOverridableDescriptor(overrides, ctx, methodName);
2022
return {
2123
...prevDescriptors,
22-
[methodName]: pd,
24+
[methodName]: overridableDescriptor,
2325
};
2426
}, {});
2527

2628
return Object.create(ctx, descriptors);
2729
}
2830

2931
/**
30-
* Creates a property descriptor for a given method on a context object, enabling custom getter and setter behavior.
32+
* Creates a property descriptor that allows overriding of a method on the given context object.
3133
*
32-
* @param store - The OverridesStore instance used to manage method overrides.
33-
* @param ctx - The context object from which the method originates.
34-
* @param method - The key of the method on the context object to create a descriptor for.
35-
* @return A property descriptor with custom getter and setter functionalities for the specified method.
34+
* This descriptor supports property overriding with functions only. It delegates method calls to
35+
* the provided store if an override exists or to the original method on the context otherwise.
36+
*
37+
* @param {OverridesStore<ContextType>} store - The storage for overridden methods specific to the context type.
38+
* @param {ContextType} ctx - The context object that contains the method to be overridden.
39+
* @param {keyof ContextType} method - The method on the context object to create the overridable descriptor for.
40+
* @return {PropertyDescriptor} A property descriptor enabling the overriding of the specified method.
3641
*/
37-
function makeMethodDescriptor(store: OverridesStore, ctx: ContextType, method: keyof ContextType): PropertyDescriptor {
42+
function makeOverridableDescriptor<T extends ContextType>(
43+
store: OverridesStore<T>,
44+
ctx: T,
45+
method: keyof T,
46+
): PropertyDescriptor {
3847
return {
3948
configurable: true,
4049
enumerable: true,
4150
set: newValue => {
42-
if(typeof newValue !== 'function') throw new Error('Cannot override non-function')
51+
if (typeof newValue !== 'function') throw new Error('Cannot override non-function');
4352
store.set(method, newValue);
4453
return true;
4554
},

0 commit comments

Comments
 (0)