Skip to content

Commit

Permalink
Enhance withSyncEvent implementation and ensure the sync flag is main…
Browse files Browse the repository at this point in the history
…tained when proxying functions via withScope.
  • Loading branch information
felixarntz committed Jan 29, 2025
1 parent b183fcd commit bf3dbcc
Showing 1 changed file with 39 additions and 18 deletions.
57 changes: 39 additions & 18 deletions packages/interactivity/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ declare global {
}
}

interface SyncAwareFunction extends Function {
sync?: boolean;
}

/**
* Executes a callback function after the next frame is rendered.
*
Expand Down Expand Up @@ -135,11 +139,14 @@ export function withScope<
? Promise< Return >
: never;
export function withScope< Func extends Function >( func: Func ): Func;
export function withScope< Func extends SyncAwareFunction >( func: Func ): Func;
export function withScope( func: ( ...args: unknown[] ) => unknown ) {
const scope = getScope();
const ns = getNamespace();

let wrapped: Function;
if ( func?.constructor?.name === 'GeneratorFunction' ) {
return async ( ...args: Parameters< typeof func > ) => {
wrapped = async ( ...args: Parameters< typeof func > ) => {
const gen = func( ...args ) as Generator;
let value: any;
let it: any;
Expand Down Expand Up @@ -171,17 +178,28 @@ export function withScope( func: ( ...args: unknown[] ) => unknown ) {

return value;
};
} else {
wrapped = ( ...args: Parameters< typeof func > ) => {
setNamespace( ns );
setScope( scope );
try {
return func( ...args );
} finally {
resetNamespace();
resetScope();
}
};
}
return ( ...args: Parameters< typeof func > ) => {
setNamespace( ns );
setScope( scope );
try {
return func( ...args );
} finally {
resetNamespace();
resetScope();
}
};

// If function was annotated via `withSyncEvent()`, maintain the annotation.
const syncAware = func as SyncAwareFunction;
if ( syncAware.sync ) {
const syncAwareWrapped = wrapped as SyncAwareFunction;
syncAwareWrapped.sync = true;
return syncAwareWrapped;
}

return wrapped;
}

/**
Expand Down Expand Up @@ -381,16 +399,19 @@ export const isPlainObject = (
* @param callback The event callback.
* @return Wrapped event callback.
*/
export const withSyncEvent = ( callback: Function ): Function => {
export function withSyncEvent( callback: Function ): SyncAwareFunction {
let wrapped: SyncAwareFunction;

if ( callback?.constructor?.name === 'GeneratorFunction' ) {
const wrapped = function* ( ...args: any[] ) {
yield* callback( ...args );
wrapped = function* ( this: any, ...args: any[] ) {
yield* callback.apply( this, args );
};
} else {
wrapped = function ( this: any, ...args: any[] ) {
return callback.apply( this, args );
};
wrapped.sync = true;
return wrapped;
}

const wrapped = ( ...args: any[] ) => callback( ...args );
wrapped.sync = true;
return wrapped;
};
}

0 comments on commit bf3dbcc

Please sign in to comment.