aboutsummaryrefslogtreecommitdiff
path: root/src/embind/emval.js
blob: b1c9ed049b95a178a0e748488579dcd3a6dbabde (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*global Module*/
/*global HEAP32*/
/*global Pointer_stringify, writeStringToMemory*/
/*global requireRegisteredType*/

var _emval_handle_array = [];
var _emval_free_list = [];

// Public JS API

/** @expose */
Module.count_emval_handles = function() {
    var count = 0;
    for (var i = 0; i < _emval_handle_array.length; ++i) {
        if (_emval_handle_array[i] !== undefined) {
            ++count;
        }
    }
    return count;
};

// Private C++ API

function __emval_register(value) {
    var handle = _emval_free_list.length ?
        _emval_free_list.pop() :
        _emval_handle_array.length;

    _emval_handle_array[handle] = {refcount: 1, value: value};
    return handle;
}

function __emval_incref(handle) {
    _emval_handle_array[handle].refcount += 1;
}

function __emval_decref(handle) {
    if (0 === --_emval_handle_array[handle].refcount) {
        delete _emval_handle_array[handle];
        _emval_free_list.push(handle);

        var actual_length = _emval_handle_array.length;
        while (actual_length > 0 && _emval_handle_array[actual_length - 1] === undefined) {
            --actual_length;
        }
        _emval_handle_array.length = actual_length;
    }
}

function __emval_new_array() {
    return __emval_register([]);
}

function __emval_new_object() {
    return __emval_register({});
}

function __emval_undefined() {
    return __emval_register(undefined);
}

function __emval_null() {
    return __emval_register(null);
}

function __emval_new_cstring(v) {
    return __emval_register(Pointer_stringify(v));
}

function __emval_take_value(type, v) {
    type = requireRegisteredType(type, '_emval_take_value');
    v = type.fromWireTypeAutoDowncast ? type.fromWireTypeAutoDowncast(v) : type.fromWireType(v);
    return __emval_register(v);
}

function __emval_new(handle) {
    return __emval_register(new (_emval_handle_array[handle].value));
}

var global = (function(){return Function;})()('return this')();

function __emval_get_global(name) {
    name = Pointer_stringify(name);
    return __emval_register(global[name]);
}

function __emval_get_property(handle, key) {
    return __emval_register(_emval_handle_array[handle].value[_emval_handle_array[key].value]);
}

function __emval_set_property(handle, key, value) {
    _emval_handle_array[handle].value[_emval_handle_array[key].value] = _emval_handle_array[value].value;
}

function __emval_as(handle, returnType) {
    returnType = requireRegisteredType(returnType, 'emval::as');
    var destructors = [];
    // caller owns destructing
    return returnType.toWireType(destructors, _emval_handle_array[handle].value);
}

function parseParameters(argCount, argTypes, argWireTypes) {
    var a = new Array(argCount);
    for (var i = 0; i < argCount; ++i) {
        var argType = requireRegisteredType(
            HEAP32[(argTypes >> 2) + i],
            "parameter " + i);
        a[i] = argType.fromWireType(argWireTypes[i]);
    }
    return a;
}

function __emval_call(handle, argCount, argTypes) {
    var fn = _emval_handle_array[handle].value;
    var args = parseParameters(
        argCount,
        argTypes,
        Array.prototype.slice.call(arguments, 3));
    var rv = fn.apply(undefined, args);
    return __emval_register(rv);
}

function __emval_call_method(handle, name, argCount, argTypes) {
    name = Pointer_stringify(name);

    var args = parseParameters(
        argCount,
        argTypes,
        Array.prototype.slice.call(arguments, 4));
    var obj = _emval_handle_array[handle].value;
    var rv = obj[name].apply(obj, args);
    return __emval_register(rv);
}

function __emval_call_void_method(handle, name, argCount, argTypes) {
    name = Pointer_stringify(name);

    var args = parseParameters(
        argCount,
        argTypes,
        Array.prototype.slice.call(arguments, 4));
    var obj = _emval_handle_array[handle].value;
    obj[name].apply(obj, args);
}