This repository has been archived by the owner on Jun 30, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
helper.ts
112 lines (95 loc) · 3.02 KB
/
helper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { dirname, join, resolve } from 'path';
import { runInNewContext } from 'vm';
import { parse as acornParse, IParseOptions } from 'acorn';
import { attachComments } from 'estraverse';
import { generate as escodegenGenerate } from 'escodegen';
import { merge } from 'lodash';
import { oneLine } from 'common-tags';
import { IHost } from '../src/host';
export class HostMock implements IHost {
public pathSep: string = '/';
public basePath: string = process.cwd();
public files: any = {};
constructor(files: {[path: string]: string}, basePath: string = process.cwd()) {
this.fileExists = this.fileExists.bind(this);
this.isFile = this.isFile.bind(this);
this.readFile = this.readFile.bind(this);
this.joinPath = this.joinPath.bind(this);
this.dirname = this.dirname.bind(this);
this.basePath = basePath;
this.files = Object
.keys(files)
.reduce((registry: any, propertyName: string) => {
const resolved = resolve(this.basePath, propertyName);
registry[resolved] = files[propertyName];
return registry;
}, {});
}
public cwd(): string {
return this.basePath;
}
public fileExists(filePath: string): boolean {
return filePath in this.files;
}
public isFile(filePath: string): boolean {
return filePath in this.files;
}
public readFile(filePath: string): string {
if (this.fileExists(filePath)) {
return this.files[filePath];
}
throw new Error(oneLine`ENOENT: Could not read file ${filePath} from HostMock fs.
Available files: ${Object.keys(this.files)}`);
}
public writeFile(filePath: string, content: string): void {
this.files[filePath] = content;
}
public joinPath(...paths: string[]): string {
return join(...paths);
}
public dirname(filePath: string): string {
return dirname(filePath);
}
}
export function parse(input: string): ESTree.Program {
const comments: any[] = [];
const tokens: any[] = [];
const acornOptions: IParseOptions = {
ecmaVersion: 7,
sourceType: 'module',
locations: true,
ranges: true,
allowHashBang: true,
onComment: comments,
onToken: tokens
};
const ast = acornParse(input, acornOptions);
attachComments(ast, comments, tokens);
return ast;
}
export function generate(ast: ESTree.Program): string {
return escodegenGenerate(ast, {comment: true}).trim();
}
export function parseAndProcess(input: string, fn: (ast: ESTree.Program) => void): string {
const ast = parse(input);
fn(ast);
return generate(ast);
}
const defaultSandbox = {
console,
module: {
exports: {}
},
require
};
export type virtualModuleResult = {[name: string]: any};
export function virtualModule(code: string, optionsSandbox = {}, requireResults: any[] = []): virtualModuleResult {
const sandbox: any = merge({}, defaultSandbox, optionsSandbox);
if (requireResults.length > 0) {
sandbox.__paeckchen_require__ = function(idx: number): any {
return requireResults[idx];
};
}
runInNewContext(code, sandbox);
return sandbox.module.exports;
}