-
Notifications
You must be signed in to change notification settings - Fork 1
/
Evaluators.ts
88 lines (81 loc) · 3.48 KB
/
Evaluators.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
import { Module, setParentGlobalThis, setParentImportHook, setParentImportMetaHook } from './Module.js'
import type { ModuleSource } from './ModuleSource.js'
import type { ImportHook, ModuleHandler, VirtualModuleRecord } from './types.js'
export interface EvaluatorsOptions {
globalThis?: object | undefined
importHook?: ImportHook | undefined
importMeta?: object | null | undefined
}
export class Evaluators {
Module: typeof Module
Evaluators: typeof Evaluators
get globalThis() {
return this.#AssignGlobalThis
}
// We do not support `eval` and `Function`.
eval = eval
Function = Function
// implementation
constructor(handler: EvaluatorsOptions) {
const { globalThis, importHook, importMeta } = handler
this.#Handler = handler
if (typeof globalThis !== 'object' && globalThis !== undefined)
throw new TypeError('globalThis must be an object')
if (typeof importHook !== 'function' && importHook !== undefined)
throw new TypeError('importHook must be a function')
if (typeof importMeta !== 'object' && importMeta !== undefined && importMeta !== null)
throw new TypeError('importMeta must be an object')
const parent = this
class Evaluators extends TopEvaluators {
constructor(options: EvaluatorsOptions) {
super(options)
this.#ParentEvaluator = parent
}
}
class Module extends TopModule {
constructor(moduleSource: ModuleSource | VirtualModuleRecord, handler: ModuleHandler) {
super(moduleSource, handler)
setParentGlobalThis(this, (parent.#CalculatedGlobalThis ??= parent.#GetGlobalThis()))
setParentImportHook(this, (parent.#CalculatedImportHook ??= parent.#GetImportHook()))
setParentImportMetaHook(this, (meta) =>
Object.assign(meta, (parent.#CalculatedImportMeta ??= parent.#GetImportMeta())),
)
}
}
this.#AssignedImportHook = importHook
this.#AssignedImportMeta = importMeta
this.#AssignGlobalThis = globalThis
this.Module = Module
this.Evaluators = Evaluators
}
#ParentEvaluator: Evaluators | undefined
#AssignGlobalThis: object | undefined
#AssignedImportHook: ImportHook | undefined
#AssignedImportMeta: object | undefined | null
#CalculatedGlobalThis: object | undefined
#CalculatedImportHook: ImportHook | undefined
#CalculatedImportMeta: object | undefined | null
#Handler: EvaluatorsOptions
#GetGlobalThis(): object {
if (this.#AssignGlobalThis) return this.#AssignGlobalThis
if (this.#ParentEvaluator) return this.#ParentEvaluator.#GetGlobalThis()
return realGlobalThis
}
#GetImportHook(): ImportHook {
if (this.#AssignedImportHook) return this.#AssignedImportHook.bind(this.#Handler)
if (this.#ParentEvaluator) return this.#ParentEvaluator.#GetImportHook()
return defaultImportHook
}
#GetImportMeta(): ImportMeta | null {
if (this.#AssignedImportMeta) return this.#AssignedImportMeta
if (this.#ParentEvaluator) return this.#ParentEvaluator.#GetImportMeta()
return null
}
}
const TopEvaluators = Evaluators
const TopModule = Module
const realGlobalThis = globalThis
/** @internal */
export function defaultImportHook(): never {
throw new TypeError(`This evaluator does not have any import resolution strategy.`)
}