fcs
2025-04-10 0163870d662dc5b7d69ceff977490ede594f7d82
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
'use strict';
 
// eslint-disable-next-line no-invalid-this, no-shadow
const {GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, global, internal, host, hook} = this;
const {Contextify, Decontextify} = internal;
// eslint-disable-next-line no-shadow
const {Function, eval: eval_, Promise, Object, Reflect} = global;
const {getOwnPropertyDescriptor, defineProperty, assign} = Object;
const {apply: rApply, construct: rConstruct} = Reflect;
 
const FunctionHandler = {
    __proto__: null,
    apply(target, thiz, args) {
        const type = this.type;
        args = Decontextify.arguments(args);
        try {
            args = Contextify.value(hook(type, args));
        } catch (e) {
            throw Contextify.value(e);
        }
        return rApply(target, thiz, args);
    },
    construct(target, args, newTarget) {
        const type = this.type;
        args = Decontextify.arguments(args);
        try {
            args = Contextify.value(hook(type, args));
        } catch (e) {
            throw Contextify.value(e);
        }
        return rConstruct(target, args, newTarget);
    }
};
 
function makeCheckFunction(type) {
    return assign({
        __proto__: null,
        type
    }, FunctionHandler);
}
 
function override(obj, prop, value) {
    const desc = getOwnPropertyDescriptor(obj, prop);
    desc.value = value;
    defineProperty(obj, prop, desc);
}
 
const proxiedFunction = new host.Proxy(Function, makeCheckFunction('function'));
override(Function.prototype, 'constructor', proxiedFunction);
if (GeneratorFunction) {
    Object.setPrototypeOf(GeneratorFunction, proxiedFunction);
    override(GeneratorFunction.prototype, 'constructor', new host.Proxy(GeneratorFunction, makeCheckFunction('generator_function')));
}
if (AsyncFunction) {
    Object.setPrototypeOf(AsyncFunction, proxiedFunction);
    override(AsyncFunction.prototype, 'constructor', new host.Proxy(AsyncFunction, makeCheckFunction('async_function')));
}
if (AsyncGeneratorFunction) {
    Object.setPrototypeOf(AsyncGeneratorFunction, proxiedFunction);
    override(AsyncGeneratorFunction.prototype, 'constructor', new host.Proxy(AsyncGeneratorFunction, makeCheckFunction('async_generator_function')));
}
 
global.Function = proxiedFunction;
global.eval = new host.Proxy(eval_, makeCheckFunction('eval'));
 
if (Promise) {
 
    Promise.prototype.then = new host.Proxy(Promise.prototype.then, makeCheckFunction('promise_then'));
    // This seems not to work, and will produce
    // UnhandledPromiseRejectionWarning: TypeError: Method Promise.prototype.then called on incompatible receiver [object Object].
    // This is likely caused since the host.Promise.prototype.then cannot use the VM Proxy object.
    // Contextify.connect(host.Promise.prototype.then, Promise.prototype.then);
 
    if (Promise.prototype.finally) {
        Promise.prototype.finally = new host.Proxy(Promise.prototype.finally, makeCheckFunction('promise_finally'));
        // Contextify.connect(host.Promise.prototype.finally, Promise.prototype.finally);
    }
    if (Promise.prototype.catch) {
        Promise.prototype.catch = new host.Proxy(Promise.prototype.catch, makeCheckFunction('promise_catch'));
        // Contextify.connect(host.Promise.prototype.catch, Promise.prototype.catch);
    }
 
}