zig-pug 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +346 -0
- package/binding.c +375 -0
- package/binding.gyp +28 -0
- package/common.gypi +5 -0
- package/include/zigpug.h +135 -0
- package/index.js +205 -0
- package/package.json +87 -0
- package/vendor/mujs/COPYING +16 -0
- package/vendor/mujs/README +50 -0
- package/vendor/mujs/astnames.h +92 -0
- package/vendor/mujs/jsarray.c +832 -0
- package/vendor/mujs/jsboolean.c +38 -0
- package/vendor/mujs/jsbuiltin.c +249 -0
- package/vendor/mujs/jscompile.c +1428 -0
- package/vendor/mujs/jsdate.c +861 -0
- package/vendor/mujs/jsdtoa.c +749 -0
- package/vendor/mujs/jserror.c +139 -0
- package/vendor/mujs/jsfunction.c +231 -0
- package/vendor/mujs/jsgc.c +284 -0
- package/vendor/mujs/jsi.h +870 -0
- package/vendor/mujs/jsintern.c +137 -0
- package/vendor/mujs/jslex.c +878 -0
- package/vendor/mujs/jsmath.c +194 -0
- package/vendor/mujs/jsnumber.c +198 -0
- package/vendor/mujs/jsobject.c +560 -0
- package/vendor/mujs/json.c +422 -0
- package/vendor/mujs/jsparse.c +1065 -0
- package/vendor/mujs/jsproperty.c +341 -0
- package/vendor/mujs/jsregexp.c +232 -0
- package/vendor/mujs/jsrepr.c +285 -0
- package/vendor/mujs/jsrun.c +2096 -0
- package/vendor/mujs/jsstate.c +334 -0
- package/vendor/mujs/jsstring.c +852 -0
- package/vendor/mujs/jsvalue.c +708 -0
- package/vendor/mujs/libmujs.a +0 -0
- package/vendor/mujs/main.c +396 -0
- package/vendor/mujs/mujs.h +253 -0
- package/vendor/mujs/one.c +25 -0
- package/vendor/mujs/opnames.h +85 -0
- package/vendor/mujs/pp.c +980 -0
- package/vendor/mujs/regexp.c +1277 -0
- package/vendor/mujs/regexp.h +46 -0
- package/vendor/mujs/utf.c +305 -0
- package/vendor/mujs/utf.h +52 -0
- package/vendor/mujs/utfdata.h +2209 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#include "jsi.h"
|
|
2
|
+
|
|
3
|
+
#define QQ(X) #X
|
|
4
|
+
#define Q(X) QQ(X)
|
|
5
|
+
|
|
6
|
+
static int jsB_stacktrace(js_State *J, int skip)
|
|
7
|
+
{
|
|
8
|
+
char buf[256];
|
|
9
|
+
int n = J->tracetop - skip;
|
|
10
|
+
if (n <= 0)
|
|
11
|
+
return 0;
|
|
12
|
+
for (; n > 0; --n) {
|
|
13
|
+
const char *name = J->trace[n].name;
|
|
14
|
+
const char *file = J->trace[n].file;
|
|
15
|
+
int line = J->trace[n].line;
|
|
16
|
+
if (line > 0) {
|
|
17
|
+
if (name[0])
|
|
18
|
+
snprintf(buf, sizeof buf, "\n\tat %s (%s:%d)", name, file, line);
|
|
19
|
+
else
|
|
20
|
+
snprintf(buf, sizeof buf, "\n\tat %s:%d", file, line);
|
|
21
|
+
} else
|
|
22
|
+
snprintf(buf, sizeof buf, "\n\tat %s (%s)", name, file);
|
|
23
|
+
js_pushstring(J, buf);
|
|
24
|
+
if (n < J->tracetop - skip)
|
|
25
|
+
js_concat(J);
|
|
26
|
+
}
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static void Ep_toString(js_State *J)
|
|
31
|
+
{
|
|
32
|
+
const char *name = "Error";
|
|
33
|
+
const char *message = "";
|
|
34
|
+
|
|
35
|
+
if (!js_isobject(J, -1))
|
|
36
|
+
js_typeerror(J, "not an object");
|
|
37
|
+
|
|
38
|
+
if (js_hasproperty(J, 0, "name"))
|
|
39
|
+
name = js_tostring(J, -1);
|
|
40
|
+
if (js_hasproperty(J, 0, "message"))
|
|
41
|
+
message = js_tostring(J, -1);
|
|
42
|
+
|
|
43
|
+
if (name[0] == 0)
|
|
44
|
+
js_pushstring(J, message);
|
|
45
|
+
else if (message[0] == 0)
|
|
46
|
+
js_pushstring(J, name);
|
|
47
|
+
else {
|
|
48
|
+
js_pushstring(J, name);
|
|
49
|
+
js_pushstring(J, ": ");
|
|
50
|
+
js_concat(J);
|
|
51
|
+
js_pushstring(J, message);
|
|
52
|
+
js_concat(J);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static void Ep_get_stack(js_State *J)
|
|
57
|
+
{
|
|
58
|
+
Ep_toString(J);
|
|
59
|
+
js_getproperty(J, 0, "stackTrace");
|
|
60
|
+
js_concat(J);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static int jsB_ErrorX(js_State *J, js_Object *prototype)
|
|
64
|
+
{
|
|
65
|
+
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
|
|
66
|
+
if (js_isdefined(J, 1)) {
|
|
67
|
+
js_pushstring(J, js_tostring(J, 1));
|
|
68
|
+
js_defproperty(J, -2, "message", JS_DONTENUM);
|
|
69
|
+
}
|
|
70
|
+
if (jsB_stacktrace(J, 1))
|
|
71
|
+
js_defproperty(J, -2, "stackTrace", JS_DONTENUM);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static void js_newerrorx(js_State *J, const char *message, js_Object *prototype)
|
|
76
|
+
{
|
|
77
|
+
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
|
|
78
|
+
js_pushstring(J, message);
|
|
79
|
+
js_setproperty(J, -2, "message");
|
|
80
|
+
if (jsB_stacktrace(J, 0))
|
|
81
|
+
js_setproperty(J, -2, "stackTrace");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#define DERROR(name, Name) \
|
|
85
|
+
static void jsB_##Name(js_State *J) { \
|
|
86
|
+
jsB_ErrorX(J, J->Name##_prototype); \
|
|
87
|
+
} \
|
|
88
|
+
void js_new##name(js_State *J, const char *s) { \
|
|
89
|
+
js_newerrorx(J, s, J->Name##_prototype); \
|
|
90
|
+
} \
|
|
91
|
+
void js_##name(js_State *J, const char *fmt, ...) { \
|
|
92
|
+
va_list ap; \
|
|
93
|
+
char buf[256]; \
|
|
94
|
+
va_start(ap, fmt); \
|
|
95
|
+
vsnprintf(buf, sizeof buf, fmt, ap); \
|
|
96
|
+
va_end(ap); \
|
|
97
|
+
js_newerrorx(J, buf, J->Name##_prototype); \
|
|
98
|
+
js_throw(J); \
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
DERROR(error, Error)
|
|
102
|
+
DERROR(evalerror, EvalError)
|
|
103
|
+
DERROR(rangeerror, RangeError)
|
|
104
|
+
DERROR(referenceerror, ReferenceError)
|
|
105
|
+
DERROR(syntaxerror, SyntaxError)
|
|
106
|
+
DERROR(typeerror, TypeError)
|
|
107
|
+
DERROR(urierror, URIError)
|
|
108
|
+
|
|
109
|
+
#undef DERROR
|
|
110
|
+
|
|
111
|
+
void jsB_initerror(js_State *J)
|
|
112
|
+
{
|
|
113
|
+
js_pushobject(J, J->Error_prototype);
|
|
114
|
+
{
|
|
115
|
+
jsB_props(J, "name", "Error");
|
|
116
|
+
jsB_propf(J, "Error.prototype.toString", Ep_toString, 0);
|
|
117
|
+
|
|
118
|
+
js_newcfunction(J, Ep_get_stack, "stack", 0);
|
|
119
|
+
js_pushnull(J);
|
|
120
|
+
js_defaccessor(J, -3, "stack", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
|
121
|
+
}
|
|
122
|
+
js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1);
|
|
123
|
+
js_defglobal(J, "Error", JS_DONTENUM);
|
|
124
|
+
|
|
125
|
+
#define IERROR(NAME) \
|
|
126
|
+
js_pushobject(J, J->NAME##_prototype); \
|
|
127
|
+
jsB_props(J, "name", Q(NAME)); \
|
|
128
|
+
js_newcconstructor(J, jsB_##NAME, jsB_##NAME, Q(NAME), 1); \
|
|
129
|
+
js_defglobal(J, Q(NAME), JS_DONTENUM);
|
|
130
|
+
|
|
131
|
+
IERROR(EvalError);
|
|
132
|
+
IERROR(RangeError);
|
|
133
|
+
IERROR(ReferenceError);
|
|
134
|
+
IERROR(SyntaxError);
|
|
135
|
+
IERROR(TypeError);
|
|
136
|
+
IERROR(URIError);
|
|
137
|
+
|
|
138
|
+
#undef IERROR
|
|
139
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#include "jsi.h"
|
|
2
|
+
|
|
3
|
+
static void jsB_Function(js_State *J)
|
|
4
|
+
{
|
|
5
|
+
int i, top = js_gettop(J);
|
|
6
|
+
js_Buffer *sb = NULL;
|
|
7
|
+
const char *body;
|
|
8
|
+
js_Ast *parse;
|
|
9
|
+
js_Function *fun;
|
|
10
|
+
|
|
11
|
+
if (js_try(J)) {
|
|
12
|
+
js_free(J, sb);
|
|
13
|
+
jsP_freeparse(J);
|
|
14
|
+
js_throw(J);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* p1, p2, ..., pn */
|
|
18
|
+
if (top > 2) {
|
|
19
|
+
for (i = 1; i < top - 1; ++i) {
|
|
20
|
+
if (i > 1)
|
|
21
|
+
js_putc(J, &sb, ',');
|
|
22
|
+
js_puts(J, &sb, js_tostring(J, i));
|
|
23
|
+
}
|
|
24
|
+
js_putc(J, &sb, ')');
|
|
25
|
+
js_putc(J, &sb, 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* body */
|
|
29
|
+
body = js_isdefined(J, top - 1) ? js_tostring(J, top - 1) : "";
|
|
30
|
+
|
|
31
|
+
parse = jsP_parsefunction(J, "[string]", sb ? sb->s : NULL, body);
|
|
32
|
+
fun = jsC_compilefunction(J, parse);
|
|
33
|
+
|
|
34
|
+
js_endtry(J);
|
|
35
|
+
js_free(J, sb);
|
|
36
|
+
jsP_freeparse(J);
|
|
37
|
+
|
|
38
|
+
js_newfunction(J, fun, J->GE);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static void jsB_Function_prototype(js_State *J)
|
|
42
|
+
{
|
|
43
|
+
js_pushundefined(J);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static void Fp_toString(js_State *J)
|
|
47
|
+
{
|
|
48
|
+
js_Object *self = js_toobject(J, 0);
|
|
49
|
+
js_Buffer *sb = NULL;
|
|
50
|
+
int i;
|
|
51
|
+
|
|
52
|
+
if (!js_iscallable(J, 0))
|
|
53
|
+
js_typeerror(J, "not a function");
|
|
54
|
+
|
|
55
|
+
if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) {
|
|
56
|
+
js_Function *F = self->u.f.function;
|
|
57
|
+
|
|
58
|
+
if (js_try(J)) {
|
|
59
|
+
js_free(J, sb);
|
|
60
|
+
js_throw(J);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
js_puts(J, &sb, "function ");
|
|
64
|
+
js_puts(J, &sb, F->name);
|
|
65
|
+
js_putc(J, &sb, '(');
|
|
66
|
+
for (i = 0; i < F->numparams; ++i) {
|
|
67
|
+
if (i > 0) js_putc(J, &sb, ',');
|
|
68
|
+
js_puts(J, &sb, F->vartab[i]);
|
|
69
|
+
}
|
|
70
|
+
js_puts(J, &sb, ") { [byte code] }");
|
|
71
|
+
js_putc(J, &sb, 0);
|
|
72
|
+
|
|
73
|
+
js_pushstring(J, sb->s);
|
|
74
|
+
js_endtry(J);
|
|
75
|
+
js_free(J, sb);
|
|
76
|
+
} else if (self->type == JS_CCFUNCTION) {
|
|
77
|
+
if (js_try(J)) {
|
|
78
|
+
js_free(J, sb);
|
|
79
|
+
js_throw(J);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
js_puts(J, &sb, "function ");
|
|
83
|
+
js_puts(J, &sb, self->u.c.name);
|
|
84
|
+
js_puts(J, &sb, "() { [native code] }");
|
|
85
|
+
js_putc(J, &sb, 0);
|
|
86
|
+
|
|
87
|
+
js_pushstring(J, sb->s);
|
|
88
|
+
js_endtry(J);
|
|
89
|
+
js_free(J, sb);
|
|
90
|
+
} else {
|
|
91
|
+
js_pushliteral(J, "function () { }");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static void Fp_apply(js_State *J)
|
|
96
|
+
{
|
|
97
|
+
int i, n;
|
|
98
|
+
|
|
99
|
+
if (!js_iscallable(J, 0))
|
|
100
|
+
js_typeerror(J, "not a function");
|
|
101
|
+
|
|
102
|
+
js_copy(J, 0);
|
|
103
|
+
js_copy(J, 1);
|
|
104
|
+
|
|
105
|
+
if (js_isnull(J, 2) || js_isundefined(J, 2)) {
|
|
106
|
+
n = 0;
|
|
107
|
+
} else {
|
|
108
|
+
n = js_getlength(J, 2);
|
|
109
|
+
if (n < 0)
|
|
110
|
+
n = 0;
|
|
111
|
+
for (i = 0; i < n; ++i)
|
|
112
|
+
js_getindex(J, 2, i);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
js_call(J, n);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static void Fp_call(js_State *J)
|
|
119
|
+
{
|
|
120
|
+
int i, top = js_gettop(J);
|
|
121
|
+
|
|
122
|
+
if (!js_iscallable(J, 0))
|
|
123
|
+
js_typeerror(J, "not a function");
|
|
124
|
+
|
|
125
|
+
for (i = 0; i < top; ++i)
|
|
126
|
+
js_copy(J, i);
|
|
127
|
+
|
|
128
|
+
js_call(J, top - 2);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static void callbound(js_State *J)
|
|
132
|
+
{
|
|
133
|
+
int top = js_gettop(J);
|
|
134
|
+
int i, fun, args, n;
|
|
135
|
+
|
|
136
|
+
fun = js_gettop(J);
|
|
137
|
+
js_currentfunction(J);
|
|
138
|
+
js_getproperty(J, fun, "__TargetFunction__");
|
|
139
|
+
js_getproperty(J, fun, "__BoundThis__");
|
|
140
|
+
|
|
141
|
+
args = js_gettop(J);
|
|
142
|
+
js_getproperty(J, fun, "__BoundArguments__");
|
|
143
|
+
n = js_getlength(J, args);
|
|
144
|
+
if (n < 0)
|
|
145
|
+
n = 0;
|
|
146
|
+
for (i = 0; i < n; ++i)
|
|
147
|
+
js_getindex(J, args, i);
|
|
148
|
+
js_remove(J, args);
|
|
149
|
+
|
|
150
|
+
for (i = 1; i < top; ++i)
|
|
151
|
+
js_copy(J, i);
|
|
152
|
+
|
|
153
|
+
js_call(J, n + top - 1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static void constructbound(js_State *J)
|
|
157
|
+
{
|
|
158
|
+
int top = js_gettop(J);
|
|
159
|
+
int i, fun, args, n;
|
|
160
|
+
|
|
161
|
+
fun = js_gettop(J);
|
|
162
|
+
js_currentfunction(J);
|
|
163
|
+
js_getproperty(J, fun, "__TargetFunction__");
|
|
164
|
+
|
|
165
|
+
args = js_gettop(J);
|
|
166
|
+
js_getproperty(J, fun, "__BoundArguments__");
|
|
167
|
+
n = js_getlength(J, args);
|
|
168
|
+
if (n < 0)
|
|
169
|
+
n = 0;
|
|
170
|
+
for (i = 0; i < n; ++i)
|
|
171
|
+
js_getindex(J, args, i);
|
|
172
|
+
js_remove(J, args);
|
|
173
|
+
|
|
174
|
+
for (i = 1; i < top; ++i)
|
|
175
|
+
js_copy(J, i);
|
|
176
|
+
|
|
177
|
+
js_construct(J, n + top - 1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static void Fp_bind(js_State *J)
|
|
181
|
+
{
|
|
182
|
+
int i, top = js_gettop(J);
|
|
183
|
+
int n;
|
|
184
|
+
|
|
185
|
+
if (!js_iscallable(J, 0))
|
|
186
|
+
js_typeerror(J, "not a function");
|
|
187
|
+
|
|
188
|
+
n = js_getlength(J, 0);
|
|
189
|
+
if (n > top - 2)
|
|
190
|
+
n -= top - 2;
|
|
191
|
+
else
|
|
192
|
+
n = 0;
|
|
193
|
+
|
|
194
|
+
/* Reuse target function's prototype for HasInstance check. */
|
|
195
|
+
js_getproperty(J, 0, "prototype");
|
|
196
|
+
js_newcconstructor(J, callbound, constructbound, "[bind]", n);
|
|
197
|
+
|
|
198
|
+
/* target function */
|
|
199
|
+
js_copy(J, 0);
|
|
200
|
+
js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
|
201
|
+
|
|
202
|
+
/* bound this */
|
|
203
|
+
js_copy(J, 1);
|
|
204
|
+
js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
|
205
|
+
|
|
206
|
+
/* bound arguments */
|
|
207
|
+
js_newarray(J);
|
|
208
|
+
for (i = 2; i < top; ++i) {
|
|
209
|
+
js_copy(J, i);
|
|
210
|
+
js_setindex(J, -2, i - 2);
|
|
211
|
+
}
|
|
212
|
+
js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void jsB_initfunction(js_State *J)
|
|
216
|
+
{
|
|
217
|
+
J->Function_prototype->u.c.name = "Function.prototype";
|
|
218
|
+
J->Function_prototype->u.c.function = jsB_Function_prototype;
|
|
219
|
+
J->Function_prototype->u.c.constructor = NULL;
|
|
220
|
+
J->Function_prototype->u.c.length = 0;
|
|
221
|
+
|
|
222
|
+
js_pushobject(J, J->Function_prototype);
|
|
223
|
+
{
|
|
224
|
+
jsB_propf(J, "Function.prototype.toString", Fp_toString, 2);
|
|
225
|
+
jsB_propf(J, "Function.prototype.apply", Fp_apply, 2);
|
|
226
|
+
jsB_propf(J, "Function.prototype.call", Fp_call, 1);
|
|
227
|
+
jsB_propf(J, "Function.prototype.bind", Fp_bind, 1);
|
|
228
|
+
}
|
|
229
|
+
js_newcconstructor(J, jsB_Function, jsB_Function, "Function", 1);
|
|
230
|
+
js_defglobal(J, "Function", JS_DONTENUM);
|
|
231
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#include "jsi.h"
|
|
2
|
+
#include "regexp.h"
|
|
3
|
+
|
|
4
|
+
static void jsG_freeenvironment(js_State *J, js_Environment *env)
|
|
5
|
+
{
|
|
6
|
+
js_free(J, env);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static void jsG_freefunction(js_State *J, js_Function *fun)
|
|
10
|
+
{
|
|
11
|
+
js_free(J, fun->funtab);
|
|
12
|
+
js_free(J, fun->vartab);
|
|
13
|
+
js_free(J, fun->code);
|
|
14
|
+
js_free(J, fun);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static void jsG_freeproperty(js_State *J, js_Property *node)
|
|
18
|
+
{
|
|
19
|
+
if (node->left->level) jsG_freeproperty(J, node->left);
|
|
20
|
+
if (node->right->level) jsG_freeproperty(J, node->right);
|
|
21
|
+
js_free(J, node);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static void jsG_freeiterator(js_State *J, js_Iterator *node)
|
|
25
|
+
{
|
|
26
|
+
while (node) {
|
|
27
|
+
js_Iterator *next = node->next;
|
|
28
|
+
js_free(J, node);
|
|
29
|
+
node = next;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static void jsG_freeobject(js_State *J, js_Object *obj)
|
|
34
|
+
{
|
|
35
|
+
if (obj->properties->level)
|
|
36
|
+
jsG_freeproperty(J, obj->properties);
|
|
37
|
+
if (obj->type == JS_CREGEXP) {
|
|
38
|
+
js_free(J, obj->u.r.source);
|
|
39
|
+
js_regfreex(J->alloc, J->actx, obj->u.r.prog);
|
|
40
|
+
}
|
|
41
|
+
if (obj->type == JS_CSTRING) {
|
|
42
|
+
if (obj->u.s.string != obj->u.s.shrstr)
|
|
43
|
+
js_free(J, obj->u.s.string);
|
|
44
|
+
}
|
|
45
|
+
if (obj->type == JS_CARRAY && obj->u.a.simple)
|
|
46
|
+
js_free(J, obj->u.a.array);
|
|
47
|
+
if (obj->type == JS_CITERATOR)
|
|
48
|
+
jsG_freeiterator(J, obj->u.iter.head);
|
|
49
|
+
if (obj->type == JS_CUSERDATA && obj->u.user.finalize)
|
|
50
|
+
obj->u.user.finalize(J, obj->u.user.data);
|
|
51
|
+
if (obj->type == JS_CCFUNCTION && obj->u.c.finalize)
|
|
52
|
+
obj->u.c.finalize(J, obj->u.c.data);
|
|
53
|
+
js_free(J, obj);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Mark and add object to scan queue */
|
|
57
|
+
static void jsG_markobject(js_State *J, int mark, js_Object *obj)
|
|
58
|
+
{
|
|
59
|
+
obj->gcmark = mark;
|
|
60
|
+
obj->gcroot = J->gcroot;
|
|
61
|
+
J->gcroot = obj;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static void jsG_markfunction(js_State *J, int mark, js_Function *fun)
|
|
65
|
+
{
|
|
66
|
+
int i;
|
|
67
|
+
fun->gcmark = mark;
|
|
68
|
+
for (i = 0; i < fun->funlen; ++i)
|
|
69
|
+
if (fun->funtab[i]->gcmark != mark)
|
|
70
|
+
jsG_markfunction(J, mark, fun->funtab[i]);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static void jsG_markenvironment(js_State *J, int mark, js_Environment *env)
|
|
74
|
+
{
|
|
75
|
+
do {
|
|
76
|
+
env->gcmark = mark;
|
|
77
|
+
if (env->variables->gcmark != mark)
|
|
78
|
+
jsG_markobject(J, mark, env->variables);
|
|
79
|
+
env = env->outer;
|
|
80
|
+
} while (env && env->gcmark != mark);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static void jsG_markproperty(js_State *J, int mark, js_Property *node)
|
|
84
|
+
{
|
|
85
|
+
if (node->left->level) jsG_markproperty(J, mark, node->left);
|
|
86
|
+
if (node->right->level) jsG_markproperty(J, mark, node->right);
|
|
87
|
+
|
|
88
|
+
if (node->value.t.type == JS_TMEMSTR && node->value.u.memstr->gcmark != mark)
|
|
89
|
+
node->value.u.memstr->gcmark = mark;
|
|
90
|
+
if (node->value.t.type == JS_TOBJECT && node->value.u.object->gcmark != mark)
|
|
91
|
+
jsG_markobject(J, mark, node->value.u.object);
|
|
92
|
+
if (node->getter && node->getter->gcmark != mark)
|
|
93
|
+
jsG_markobject(J, mark, node->getter);
|
|
94
|
+
if (node->setter && node->setter->gcmark != mark)
|
|
95
|
+
jsG_markobject(J, mark, node->setter);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Mark everything the object can reach. */
|
|
99
|
+
static void jsG_scanobject(js_State *J, int mark, js_Object *obj)
|
|
100
|
+
{
|
|
101
|
+
if (obj->properties->level)
|
|
102
|
+
jsG_markproperty(J, mark, obj->properties);
|
|
103
|
+
if (obj->prototype && obj->prototype->gcmark != mark)
|
|
104
|
+
jsG_markobject(J, mark, obj->prototype);
|
|
105
|
+
if (obj->type == JS_CARRAY && obj->u.a.simple) {
|
|
106
|
+
int i;
|
|
107
|
+
for (i = 0; i < obj->u.a.flat_length; ++i) {
|
|
108
|
+
js_Value *v = &obj->u.a.array[i];
|
|
109
|
+
if (v->t.type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
|
|
110
|
+
v->u.memstr->gcmark = mark;
|
|
111
|
+
if (v->t.type == JS_TOBJECT && v->u.object->gcmark != mark)
|
|
112
|
+
jsG_markobject(J, mark, v->u.object);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (obj->type == JS_CITERATOR && obj->u.iter.target->gcmark != mark) {
|
|
116
|
+
jsG_markobject(J, mark, obj->u.iter.target);
|
|
117
|
+
}
|
|
118
|
+
if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT) {
|
|
119
|
+
if (obj->u.f.scope && obj->u.f.scope->gcmark != mark)
|
|
120
|
+
jsG_markenvironment(J, mark, obj->u.f.scope);
|
|
121
|
+
if (obj->u.f.function && obj->u.f.function->gcmark != mark)
|
|
122
|
+
jsG_markfunction(J, mark, obj->u.f.function);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static void jsG_markstack(js_State *J, int mark)
|
|
127
|
+
{
|
|
128
|
+
js_Value *v = J->stack;
|
|
129
|
+
int n = J->top;
|
|
130
|
+
while (n--) {
|
|
131
|
+
if (v->t.type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
|
|
132
|
+
v->u.memstr->gcmark = mark;
|
|
133
|
+
if (v->t.type == JS_TOBJECT && v->u.object->gcmark != mark)
|
|
134
|
+
jsG_markobject(J, mark, v->u.object);
|
|
135
|
+
++v;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void js_gc(js_State *J, int report)
|
|
140
|
+
{
|
|
141
|
+
js_Function *fun, *nextfun, **prevnextfun;
|
|
142
|
+
js_Object *obj, *nextobj, **prevnextobj;
|
|
143
|
+
js_String *str, *nextstr, **prevnextstr;
|
|
144
|
+
js_Environment *env, *nextenv, **prevnextenv;
|
|
145
|
+
unsigned int nenv = 0, nfun = 0, nobj = 0, nstr = 0, nprop = 0;
|
|
146
|
+
unsigned int genv = 0, gfun = 0, gobj = 0, gstr = 0, gprop = 0;
|
|
147
|
+
int mark;
|
|
148
|
+
int i;
|
|
149
|
+
|
|
150
|
+
mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
|
|
151
|
+
|
|
152
|
+
/* Add initial roots. */
|
|
153
|
+
|
|
154
|
+
jsG_markobject(J, mark, J->Object_prototype);
|
|
155
|
+
jsG_markobject(J, mark, J->Array_prototype);
|
|
156
|
+
jsG_markobject(J, mark, J->Function_prototype);
|
|
157
|
+
jsG_markobject(J, mark, J->Boolean_prototype);
|
|
158
|
+
jsG_markobject(J, mark, J->Number_prototype);
|
|
159
|
+
jsG_markobject(J, mark, J->String_prototype);
|
|
160
|
+
jsG_markobject(J, mark, J->RegExp_prototype);
|
|
161
|
+
jsG_markobject(J, mark, J->Date_prototype);
|
|
162
|
+
|
|
163
|
+
jsG_markobject(J, mark, J->Error_prototype);
|
|
164
|
+
jsG_markobject(J, mark, J->EvalError_prototype);
|
|
165
|
+
jsG_markobject(J, mark, J->RangeError_prototype);
|
|
166
|
+
jsG_markobject(J, mark, J->ReferenceError_prototype);
|
|
167
|
+
jsG_markobject(J, mark, J->SyntaxError_prototype);
|
|
168
|
+
jsG_markobject(J, mark, J->TypeError_prototype);
|
|
169
|
+
jsG_markobject(J, mark, J->URIError_prototype);
|
|
170
|
+
|
|
171
|
+
jsG_markobject(J, mark, J->R);
|
|
172
|
+
jsG_markobject(J, mark, J->G);
|
|
173
|
+
|
|
174
|
+
jsG_markstack(J, mark);
|
|
175
|
+
|
|
176
|
+
jsG_markenvironment(J, mark, J->E);
|
|
177
|
+
jsG_markenvironment(J, mark, J->GE);
|
|
178
|
+
for (i = 0; i < J->envtop; ++i)
|
|
179
|
+
jsG_markenvironment(J, mark, J->envstack[i]);
|
|
180
|
+
|
|
181
|
+
/* Scan objects until none remain. */
|
|
182
|
+
|
|
183
|
+
while ((obj = J->gcroot) != NULL) {
|
|
184
|
+
J->gcroot = obj->gcroot;
|
|
185
|
+
obj->gcroot = NULL;
|
|
186
|
+
jsG_scanobject(J, mark, obj);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Free everything not marked. */
|
|
190
|
+
|
|
191
|
+
prevnextenv = &J->gcenv;
|
|
192
|
+
for (env = J->gcenv; env; env = nextenv) {
|
|
193
|
+
nextenv = env->gcnext;
|
|
194
|
+
if (env->gcmark != mark) {
|
|
195
|
+
*prevnextenv = nextenv;
|
|
196
|
+
jsG_freeenvironment(J, env);
|
|
197
|
+
++genv;
|
|
198
|
+
} else {
|
|
199
|
+
prevnextenv = &env->gcnext;
|
|
200
|
+
}
|
|
201
|
+
++nenv;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
prevnextfun = &J->gcfun;
|
|
205
|
+
for (fun = J->gcfun; fun; fun = nextfun) {
|
|
206
|
+
nextfun = fun->gcnext;
|
|
207
|
+
if (fun->gcmark != mark) {
|
|
208
|
+
*prevnextfun = nextfun;
|
|
209
|
+
jsG_freefunction(J, fun);
|
|
210
|
+
++gfun;
|
|
211
|
+
} else {
|
|
212
|
+
prevnextfun = &fun->gcnext;
|
|
213
|
+
}
|
|
214
|
+
++nfun;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
prevnextobj = &J->gcobj;
|
|
218
|
+
for (obj = J->gcobj; obj; obj = nextobj) {
|
|
219
|
+
nprop += obj->count;
|
|
220
|
+
nextobj = obj->gcnext;
|
|
221
|
+
if (obj->gcmark != mark) {
|
|
222
|
+
gprop += obj->count;
|
|
223
|
+
*prevnextobj = nextobj;
|
|
224
|
+
jsG_freeobject(J, obj);
|
|
225
|
+
++gobj;
|
|
226
|
+
} else {
|
|
227
|
+
prevnextobj = &obj->gcnext;
|
|
228
|
+
}
|
|
229
|
+
++nobj;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
prevnextstr = &J->gcstr;
|
|
233
|
+
for (str = J->gcstr; str; str = nextstr) {
|
|
234
|
+
nextstr = str->gcnext;
|
|
235
|
+
if (str->gcmark != mark) {
|
|
236
|
+
*prevnextstr = nextstr;
|
|
237
|
+
js_free(J, str);
|
|
238
|
+
++gstr;
|
|
239
|
+
} else {
|
|
240
|
+
prevnextstr = &str->gcnext;
|
|
241
|
+
}
|
|
242
|
+
++nstr;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
unsigned int ntot = nenv + nfun + nobj + nstr + nprop;
|
|
246
|
+
unsigned int gtot = genv + gfun + gobj + gstr + gprop;
|
|
247
|
+
unsigned int remaining = ntot - gtot;
|
|
248
|
+
|
|
249
|
+
J->gccounter = remaining;
|
|
250
|
+
J->gcthresh = remaining * JS_GCFACTOR;
|
|
251
|
+
|
|
252
|
+
if (report) {
|
|
253
|
+
char buf[256];
|
|
254
|
+
snprintf(buf, sizeof buf, "garbage collected (%d%%): %d/%d envs, %d/%d funs, %d/%d objs, %d/%d props, %d/%d strs",
|
|
255
|
+
100*gtot/ntot, genv, nenv, gfun, nfun, gobj, nobj, gprop, nprop, gstr, nstr);
|
|
256
|
+
js_report(J, buf);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
void js_freestate(js_State *J)
|
|
261
|
+
{
|
|
262
|
+
js_Function *fun, *nextfun;
|
|
263
|
+
js_Object *obj, *nextobj;
|
|
264
|
+
js_Environment *env, *nextenv;
|
|
265
|
+
js_String *str, *nextstr;
|
|
266
|
+
|
|
267
|
+
if (!J)
|
|
268
|
+
return;
|
|
269
|
+
|
|
270
|
+
for (env = J->gcenv; env; env = nextenv)
|
|
271
|
+
nextenv = env->gcnext, jsG_freeenvironment(J, env);
|
|
272
|
+
for (fun = J->gcfun; fun; fun = nextfun)
|
|
273
|
+
nextfun = fun->gcnext, jsG_freefunction(J, fun);
|
|
274
|
+
for (obj = J->gcobj; obj; obj = nextobj)
|
|
275
|
+
nextobj = obj->gcnext, jsG_freeobject(J, obj);
|
|
276
|
+
for (str = J->gcstr; str; str = nextstr)
|
|
277
|
+
nextstr = str->gcnext, js_free(J, str);
|
|
278
|
+
|
|
279
|
+
jsS_freestrings(J);
|
|
280
|
+
|
|
281
|
+
js_free(J, J->lexbuf.text);
|
|
282
|
+
J->alloc(J->actx, J->stack, 0);
|
|
283
|
+
J->alloc(J->actx, J, 0);
|
|
284
|
+
}
|