Skip to content

Commit e9d46e1

Browse files
authored
fix: revert scope change, use simple parameter injection
Remove block-scope var destructuring mechanism — use original function-parameter injection (new AsyncFunction(...keys, source)) to minimize risk. getOctokit is added as a standard function parameter alongside github, core, context, etc. The const/let redeclaration collision is accepted as a documented trade-off in the major version bump.
1 parent 6fcc683 commit e9d46e1

3 files changed

Lines changed: 4 additions & 115 deletions

File tree

__test__/async-function.test.ts

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,6 @@ describe('callAsyncFunction', () => {
114114
await callAsyncFunction({} as any, 'console')
115115
})
116116

117-
test('const/let redeclaration of injected names does not throw', async () => {
118-
const getOctokit = jest.fn().mockReturnValue('original')
119-
120-
// This would SyntaxError with the old function-parameter approach
121-
const result = await callAsyncFunction(
122-
{getOctokit} as any,
123-
`
124-
const getOctokit = () => 'shadowed'
125-
return getOctokit()
126-
`
127-
)
128-
129-
expect(result).toEqual('shadowed')
130-
expect(getOctokit).not.toHaveBeenCalled()
131-
})
132-
133117
test('injected names are accessible when not redeclared', async () => {
134118
const getOctokit = jest.fn().mockReturnValue('from-injected')
135119

@@ -142,66 +126,6 @@ describe('callAsyncFunction', () => {
142126
expect(getOctokit).toHaveBeenCalledWith('token')
143127
})
144128

145-
test('return from block scope returns from function', async () => {
146-
const result = await callAsyncFunction(
147-
{foo: 'bar'} as any,
148-
`return foo + '-baz'`
149-
)
150-
151-
expect(result).toEqual('bar-baz')
152-
})
153-
154-
test('top-level await works inside block scope', async () => {
155-
const result = await callAsyncFunction(
156-
{} as any,
157-
`
158-
const val = await Promise.resolve('async-value')
159-
return val
160-
`
161-
)
162-
163-
expect(result).toEqual('async-value')
164-
})
165-
166-
test('var redeclaration of injected names works (v8 compat)', async () => {
167-
const getOctokit = jest.fn().mockReturnValue('original')
168-
169-
const result = await callAsyncFunction(
170-
{getOctokit} as any,
171-
`
172-
var getOctokit = () => 'var-shadowed'
173-
return getOctokit()
174-
`
175-
)
176-
177-
expect(result).toEqual('var-shadowed')
178-
expect(getOctokit).not.toHaveBeenCalled()
179-
})
180-
181-
test('reassignment of injected names works (v8 compat)', async () => {
182-
const result = await callAsyncFunction(
183-
{foo: 'original'} as any,
184-
`
185-
foo = 'reassigned'
186-
return foo
187-
`
188-
)
189-
190-
expect(result).toEqual('reassigned')
191-
})
192-
193-
test('rejects invalid argument names', () => {
194-
expect(() =>
195-
callAsyncFunction({'bad key': 'val'} as any, 'return 1')
196-
).toThrow('Invalid argument name: bad key')
197-
})
198-
199-
test('rejects __scope__ as argument name', () => {
200-
expect(() =>
201-
callAsyncFunction({__scope__: 'val'} as any, 'return 1')
202-
).toThrow("'__scope__' is a reserved internal name")
203-
})
204-
205129
test('syntax errors in user code still throw', () => {
206130
expect(() => callAsyncFunction({} as any, 'const x = {')).toThrow(
207131
SyntaxError

dist/index.js

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64946,23 +64946,8 @@ retry.VERSION = plugin_retry_dist_bundle_VERSION;
6494664946
;// CONCATENATED MODULE: ./src/async-function.ts
6494764947
const AsyncFunction = Object.getPrototypeOf(async () => null).constructor;
6494864948
function callAsyncFunction(args, source) {
64949-
// Inject variables via var destructuring + block scope so that user
64950-
// scripts can shadow injected names with const/let (block-scoped) or
64951-
// var (function-scoped redeclaration) without SyntaxError.
64952-
// Using var (not const) preserves v8 reassignment semantics.
64953-
const keys = Object.keys(args);
64954-
// Guard: all keys must be valid JS identifiers (defensive for exported API)
64955-
const identRe = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
64956-
for (const key of keys) {
64957-
if (!identRe.test(key)) {
64958-
throw new Error(`Invalid argument name: ${key}`);
64959-
}
64960-
}
64961-
if ('__scope__' in args) {
64962-
throw new Error("'__scope__' is a reserved internal name");
64963-
}
64964-
const fn = new AsyncFunction('__scope__', `var {${keys.join(', ')}} = __scope__;\n{\n${source}\n}`);
64965-
return fn(args);
64949+
const fn = new AsyncFunction(...Object.keys(args), source);
64950+
return fn(...Object.values(args));
6496664951
}
6496764952

6496864953
;// CONCATENATED MODULE: ./src/create-configured-getoctokit.ts

src/async-function.ts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,6 @@ export function callAsyncFunction<T>(
2323
args: AsyncFunctionArguments,
2424
source: string
2525
): Promise<T> {
26-
// Inject variables via var destructuring + block scope so that user
27-
// scripts can shadow injected names with const/let (block-scoped) or
28-
// var (function-scoped redeclaration) without SyntaxError.
29-
// Using var (not const) preserves v8 reassignment semantics.
30-
const keys = Object.keys(args)
31-
32-
// Guard: all keys must be valid JS identifiers (defensive for exported API)
33-
const identRe = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/
34-
for (const key of keys) {
35-
if (!identRe.test(key)) {
36-
throw new Error(`Invalid argument name: ${key}`)
37-
}
38-
}
39-
if ('__scope__' in args) {
40-
throw new Error("'__scope__' is a reserved internal name")
41-
}
42-
43-
const fn = new AsyncFunction(
44-
'__scope__',
45-
`var {${keys.join(', ')}} = __scope__;\n{\n${source}\n}`
46-
)
47-
return fn(args)
26+
const fn = new AsyncFunction(...Object.keys(args), source)
27+
return fn(...Object.values(args))
4828
}

0 commit comments

Comments
 (0)