chore: Change back to the function-style operation

We lose the more normal looking export in favor of the `return` statement already traditional to this action, and thus can handle await statements without an ESM conversion.

This is a separate commit from the former because I think the next major version of this action should switch to ESM, revert this commit, and use the more standard export notation in all supported languages.
This commit is contained in:
Ricky C 2024-07-05 19:03:21 -07:00
parent d3f9a3b3fb
commit f27b40e6b7
4 changed files with 28 additions and 51 deletions

View file

@ -11,12 +11,12 @@ const scripts: Record<SupportedLanguage, string> = {
[SupportedLanguage.cts]: ` [SupportedLanguage.cts]: `
const FS = require('node:fs') // Proof that we are in CommonJS. const FS = require('node:fs') // Proof that we are in CommonJS.
let a: string // Proof that we are in TypeScript. let a: string // Proof that we are in TypeScript.
exports = foo // Proof that we executed correctly. return foo // Proof that we executed correctly.
`, `,
[SupportedLanguage.mts]: ` [SupportedLanguage.mts]: `
import FS from 'node:fs' // Proof that we are in an ES Module. import FS from 'node:fs' // Proof that we are in an ES Module.
let a: string // Proof that we are in TypeScript. let a: string // Proof that we are in TypeScript.
export default foo // Proof that we executed correctly. return foo // Proof that we executed correctly.
` `
} }
@ -108,7 +108,7 @@ describe(interpretScript.name, () => {
{require} as any, {require} as any,
` `
const {test} = require('../test/requireable') const {test} = require('../test/requireable')
exports = test() return test()
` `
) )
return expect(result()).resolves.toEqual('hello') return expect(result()).resolves.toEqual('hello')
@ -165,13 +165,12 @@ describe(interpretScript.name, () => {
const result = await interpretScript( const result = await interpretScript(
SupportedLanguage.mts, SupportedLanguage.mts,
{} as any, {} as any,
`export default {a: 'b'}` `return {a: 'b'}`
) )
return expect(result()).resolves.toEqual({a: 'b'}) return expect(result()).resolves.toEqual({a: 'b'})
}) })
test.skip(`a script that uses a root level await`, async () => { test(`a script that uses a root level await`, async () => {
// Will not work until we can actually run in ESM. Current code is transpiling the mts to cjs, so we don't get root level awaits yet.
const result = await interpretScript( const result = await interpretScript(
SupportedLanguage.mts, SupportedLanguage.mts,
{} as any, {} as any,
@ -180,14 +179,13 @@ describe(interpretScript.name, () => {
return expect(result()).resolves return expect(result()).resolves
}) })
test.skip(`a script imports a script from disk`, async () => { test(`a script imports a script from disk`, async () => {
// Will not work until we can actually run in ESM. Current code is transpiling the mts to cjs, so we don't get root level awaits yet.
const result = await interpretScript( const result = await interpretScript(
SupportedLanguage.mts, SupportedLanguage.mts,
{require} as any, {require} as any,
` `
const {test} = await import('../test/importable') const {test} = await import('../test/importable')
export default test() return test()
` `
) )
return expect(result()).resolves.toEqual('hello') return expect(result()).resolves.toEqual('hello')

29
dist/index.js vendored
View file

@ -213408,21 +213408,23 @@ var io = __nccwpck_require__(7436);
var dist_node = __nccwpck_require__(8883); var dist_node = __nccwpck_require__(8883);
// EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js // EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js
var plugin_retry_dist_node = __nccwpck_require__(6298); var plugin_retry_dist_node = __nccwpck_require__(6298);
;// CONCATENATED MODULE: external "node:vm"
const external_node_vm_namespaceObject = require("node:vm");
// EXTERNAL MODULE: ./node_modules/typescript/lib/typescript.js // EXTERNAL MODULE: ./node_modules/typescript/lib/typescript.js
var typescript = __nccwpck_require__(7414); var typescript = __nccwpck_require__(7414);
;// CONCATENATED MODULE: ./src/async-function.ts ;// CONCATENATED MODULE: ./src/async-function.ts
const AsyncFunction = Object.getPrototypeOf(async () => null).constructor; const AsyncFunction = Object.getPrototypeOf(async () => null).constructor;
function callAsyncFunction(args, source) { function callAsyncFunction(args, source) {
const fn = new AsyncFunction(...Object.keys(args), source); const commonJsArgs = {
return fn(...Object.values(args)); ...args,
module: { exports: {} },
exports: {}
};
const fn = new AsyncFunction(...Object.keys(commonJsArgs), source);
return fn(...Object.values(commonJsArgs));
} }
;// CONCATENATED MODULE: ./src/interpret-script.ts ;// CONCATENATED MODULE: ./src/interpret-script.ts
var SupportedLanguage; var SupportedLanguage;
(function (SupportedLanguage) { (function (SupportedLanguage) {
SupportedLanguage["cjs"] = "cjs"; SupportedLanguage["cjs"] = "cjs";
@ -213431,31 +213433,20 @@ var SupportedLanguage;
})(SupportedLanguage || (SupportedLanguage = {})); })(SupportedLanguage || (SupportedLanguage = {}));
async function interpretScript(language, context, script) { async function interpretScript(language, context, script) {
switch (language) { switch (language) {
case SupportedLanguage.cjs:
return async () => callAsyncFunction(context, script);
case SupportedLanguage.cts: case SupportedLanguage.cts:
case SupportedLanguage.mts: { case SupportedLanguage.mts: {
const fileName = `github-script.${language}`; const fileName = `github-script.${language}`;
const compilerResult = (0,typescript.transpileModule)(script, { script = (0,typescript.transpileModule)(script, {
compilerOptions: { compilerOptions: {
module: typescript.ModuleKind.CommonJS, module: typescript.ModuleKind.CommonJS,
target: typescript.ScriptTarget.Latest, target: typescript.ScriptTarget.Latest,
strict: true strict: true
}, },
fileName fileName
}); }).outputText;
return async () => {
const runContext = {
module: { exports: {} },
exports: {},
process,
...context
};
const runResult = external_node_vm_namespaceObject.runInNewContext(compilerResult.outputText, runContext);
return runResult;
};
} }
} }
return async () => callAsyncFunction(context, script);
} }
;// CONCATENATED MODULE: ./src/retry-options.ts ;// CONCATENATED MODULE: ./src/retry-options.ts

View file

@ -22,6 +22,11 @@ export function callAsyncFunction<T>(
args: AsyncFunctionArguments, args: AsyncFunctionArguments,
source: string source: string
): Promise<T> { ): Promise<T> {
const fn = new AsyncFunction(...Object.keys(args), source) const commonJsArgs = {
return fn(...Object.values(args)) ...args,
module: {exports: {}},
exports: {}
}
const fn = new AsyncFunction(...Object.keys(commonJsArgs), source)
return fn(...Object.values(commonJsArgs))
} }

View file

@ -1,5 +1,3 @@
import * as VM from 'node:vm'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as exec from '@actions/exec' import * as exec from '@actions/exec'
import {Context} from '@actions/github/lib/context' import {Context} from '@actions/github/lib/context'
@ -36,35 +34,20 @@ export async function interpretScript<T>(
script: string script: string
): Promise<() => Promise<T>> { ): Promise<() => Promise<T>> {
switch (language) { switch (language) {
case SupportedLanguage.cjs:
return async () => callAsyncFunction(context, script)
case SupportedLanguage.cts: case SupportedLanguage.cts:
case SupportedLanguage.mts: { case SupportedLanguage.mts: {
const fileName = `github-script.${language}` const fileName = `github-script.${language}`
const compilerResult = transpileModule(script, { script = transpileModule(script, {
compilerOptions: { compilerOptions: {
module: ModuleKind.CommonJS, // Take the incoming TypeScript and compile it to CommonJS to run in the CommonJS environment of this action. module: ModuleKind.CommonJS, // Take the incoming TypeScript and compile it to CommonJS to run in the CommonJS environment of this action.
target: ScriptTarget.Latest, target: ScriptTarget.Latest,
strict: true strict: true
}, },
fileName fileName
}) }).outputText
return async () => {
const runContext: CjsContext & Record<string, unknown> = {
module: {exports: {}},
exports: {},
process,
...context
}
const runResult = VM.runInNewContext(
compilerResult.outputText,
runContext
)
return runResult
}
} }
} }
return async () => callAsyncFunction(context, script)
} }