Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

Remove "generator" output mode #12

Merged
merged 3 commits into from Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [6.x, 8.x, 10.x, 12.x]
node-version: [8.x, 10.x, 12.x, 14.x]

runs-on: ${{ matrix.os }}

Expand Down
83 changes: 0 additions & 83 deletions src/generator-to-promise.ts

This file was deleted.

79 changes: 28 additions & 51 deletions src/index.ts
Expand Up @@ -4,9 +4,6 @@ import { parseScript } from 'esprima';
import { visit, namedTypes as n, builders as b } from 'ast-types';
import { Context, RunningScriptOptions, runInNewContext } from 'vm';

import _supportsAsync from './supports-async';
import generatorToPromiseFn from './generator-to-promise';

/**
* Compiles sync JavaScript code into JavaScript with async Functions.
*
Expand All @@ -18,8 +15,7 @@ import generatorToPromiseFn from './generator-to-promise';

function degenerator(
code: string,
_names: degenerator.DegeneratorNames,
{ output = 'async' }: degenerator.DegeneratorOptions = {}
_names: degenerator.DegeneratorNames
): string {
if (!Array.isArray(_names)) {
throw new TypeError('an array of async function "names" is required');
Expand Down Expand Up @@ -76,20 +72,16 @@ function degenerator(
shouldDegenerate = true;
}
return false;
}
},
});

if (!shouldDegenerate) {
return false;
}

// Got a "function" expression/statement,
// convert it into an async or generator function
if (output === 'async') {
path.node.async = true;
} else if (output === 'generator') {
path.node.generator = true;
}
// convert it into an async function
path.node.async = true;

// Add function name to `names` array
if (!checkName(path.node.id.name, names)) {
Expand All @@ -98,7 +90,7 @@ function degenerator(
}

this.traverse(path);
}
},
});
} while (lastNamesLength !== names.length);

Expand All @@ -112,19 +104,10 @@ function degenerator(
const delegate = false;
const {
name,
parent: { node: pNode }
parent: { node: pNode },
} = path;

let expr;
if (output === 'async') {
expr = b.awaitExpression(path.node, delegate);
} else if (output === 'generator') {
expr = b.yieldExpression(path.node, delegate);
} else {
throw new Error(
'Only "async" and "generator" are allowd `output` values'
);
}
const expr = b.awaitExpression(path.node, delegate);

if (n.CallExpression.check(pNode)) {
pNode.arguments[name] = expr;
Expand All @@ -134,7 +117,7 @@ function degenerator(
}

this.traverse(path);
}
},
});

return generate(ast);
Expand All @@ -143,24 +126,16 @@ function degenerator(
namespace degenerator {
export type DegeneratorName = string | RegExp;
export type DegeneratorNames = DegeneratorName[];
export type DegeneratorOutput = 'async' | 'generator';
export interface DegeneratorOptions {
output?: DegeneratorOutput;
}
export interface CompileOptions
extends DegeneratorOptions,
RunningScriptOptions {
export interface CompileOptions extends RunningScriptOptions {
sandbox?: Context;
}
export const supportsAsync = _supportsAsync;
export function compile<T extends Function>(
export function compile<R, A extends any[] = []>(
code: string,
returnName: string,
names: DegeneratorNames,
options: CompileOptions = {}
): T {
const output = _supportsAsync ? 'async' : 'generator';
const compiled = degenerator(code, names, { ...options, output });
): (...args: A) => Promise<R> {
const compiled = degenerator(code, names);
const fn = runInNewContext(
`${compiled};${returnName}`,
options.sandbox,
Expand All @@ -171,23 +146,25 @@ namespace degenerator {
`Expected a "function" to be returned for \`${returnName}\`, but got "${typeof fn}"`
);
}
if (isAsyncFunction(fn)) {
return fn;
} else {
const rtn = (generatorToPromiseFn(fn) as unknown) as T;
Object.defineProperty(rtn, 'toString', {
value: fn.toString.bind(fn),
enumerable: false
});
return rtn;
}
const r = function (this: any, ...args: A): Promise<R> {
try {
const p = fn.apply(this, args);
if (typeof p.then === 'function') {
return p;
}
return Promise.resolve(p);
} catch (err) {
return Promise.reject(err);
}
};
Object.defineProperty(r, 'toString', {
value: fn.toString.bind(fn),
enumerable: false,
});
return r;
}
}

function isAsyncFunction(fn: any): boolean {
return typeof fn === 'function' && fn.constructor.name === 'AsyncFunction';
}

/**
* Returns `true` if `node` has a matching name to one of the entries in the
* `names` array.
Expand Down
12 changes: 0 additions & 12 deletions src/supports-async.ts

This file was deleted.

8 changes: 4 additions & 4 deletions test/assignment.expected.js
Expand Up @@ -3,9 +3,9 @@ var biz = foo;
function foo() {
return 42;
}
function* bar() {
return yield baz();
async function bar() {
return await baz();
}
function* bir() {
return yield biz();
async function bir() {
return await biz();
}
4 changes: 2 additions & 2 deletions test/basic.expected.js
@@ -1,3 +1,3 @@
function* foo() {
return (yield a('bar')) || (yield b());
async function foo() {
return await a('bar') || await b();
}
8 changes: 4 additions & 4 deletions test/get-example.expected.js
@@ -1,7 +1,7 @@
function* myFn() {
var one = yield get('https://google.com');
var two = yield get('http://nodejs.org');
var three = JSON.parse(yield get('http://jsonip.org'));
async function myFn() {
var one = await get('https://google.com');
var two = await get('http://nodejs.org');
var three = JSON.parse(await get('http://jsonip.org'));
return [
one,
two,
Expand Down
12 changes: 6 additions & 6 deletions test/multiple.expected.js
@@ -1,9 +1,9 @@
function* foo() {
return yield baz();
async function foo() {
return await baz();
}
function* bar() {
return yield foo(baz);
async function bar() {
return await foo(baz);
}
function* baz() {
return yield bar();
async function baz() {
return await bar();
}
10 changes: 5 additions & 5 deletions test/pac-resolver-gh-3.expected.js
@@ -1,22 +1,22 @@
function* FindProxyForURL(url, host) {
if (yield isHostInAnySubnet(host, [
async function FindProxyForURL(url, host) {
if (await isHostInAnySubnet(host, [
'10.1.2.0',
'10.1.3.0'
], '255.255.255.0')) {
return 'HTTPS proxy.example.com';
}
if (yield isHostInAnySubnet(host, [
if (await isHostInAnySubnet(host, [
'10.2.2.0',
'10.2.3.0'
], '255.255.255.0')) {
return 'HTTPS proxy.example.com';
}
return 'DIRECT';
}
function* isHostInAnySubnet(host, subnets, mask) {
async function isHostInAnySubnet(host, subnets, mask) {
var subnets_length = subnets.length;
for (i = 0; i < subnets_length; i++) {
if (yield isInNet(host, subnets[i], mask)) {
if (await isInNet(host, subnets[i], mask)) {
return true;
}
}
Expand Down
14 changes: 7 additions & 7 deletions test/partial.expected.js
@@ -1,12 +1,12 @@
function* foo() {
return yield baz();
async function foo() {
return await baz();
}
function* bar() {
return yield foo(baz);
async function bar() {
return await foo(baz);
}
function* baz() {
return yield bar();
async function baz() {
return await bar();
}
function shouldntChange() {
return 42;
}
}