line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "easyxs/easyxs.h" |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
#include "quickjs/quickjs.h" |
4
|
|
|
|
|
|
|
#include "quickjs/quickjs-libc.h" |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#define PERL_NS_ROOT "JavaScript::QuickJS" |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#define PERL_BOOLEAN_CLASS "Types::Serialiser::Boolean" |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#define PQJS_JSOBJECT_CLASS PERL_NS_ROOT "::JSObject" |
11
|
|
|
|
|
|
|
#define PQJS_FUNCTION_CLASS PERL_NS_ROOT "::Function" |
12
|
|
|
|
|
|
|
#define PQJS_REGEXP_CLASS PERL_NS_ROOT "::RegExp" |
13
|
|
|
|
|
|
|
#define PQJS_DATE_CLASS PERL_NS_ROOT "::Date" |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
typedef struct { |
16
|
|
|
|
|
|
|
JSContext *ctx; |
17
|
|
|
|
|
|
|
pid_t pid; |
18
|
|
|
|
|
|
|
char* module_base_path; |
19
|
|
|
|
|
|
|
} perl_qjs_s; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
typedef struct { |
22
|
|
|
|
|
|
|
JSContext *ctx; |
23
|
|
|
|
|
|
|
JSValue jsobj; |
24
|
|
|
|
|
|
|
pid_t pid; |
25
|
|
|
|
|
|
|
} perl_qjs_jsobj_s; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
typedef struct { |
28
|
|
|
|
|
|
|
#ifdef MULTIPLICITY |
29
|
|
|
|
|
|
|
tTHX aTHX; |
30
|
|
|
|
|
|
|
#endif |
31
|
|
|
|
|
|
|
SV** svs; |
32
|
|
|
|
|
|
|
U32 svs_count; |
33
|
|
|
|
|
|
|
U32 refcount; |
34
|
|
|
|
|
|
|
JSValue regexp_jsvalue; |
35
|
|
|
|
|
|
|
JSValue date_jsvalue; |
36
|
|
|
|
|
|
|
} ctx_opaque_s; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
const char* __jstype_name_back[] = { |
39
|
|
|
|
|
|
|
[JS_TAG_BIG_DECIMAL - JS_TAG_FIRST] = "big decimal", |
40
|
|
|
|
|
|
|
[JS_TAG_BIG_INT - JS_TAG_FIRST] = "big integer", |
41
|
|
|
|
|
|
|
[JS_TAG_BIG_FLOAT - JS_TAG_FIRST] = "big float", |
42
|
|
|
|
|
|
|
[JS_TAG_SYMBOL - JS_TAG_FIRST] = "symbol", |
43
|
|
|
|
|
|
|
[JS_TAG_MODULE - JS_TAG_FIRST] = "module", |
44
|
|
|
|
|
|
|
[JS_TAG_OBJECT - JS_TAG_FIRST] = "object", |
45
|
|
|
|
|
|
|
[JS_TAG_FLOAT64 - JS_TAG_FIRST] = "float64", |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
/* Small hack to ensure we can always read: */ |
48
|
|
|
|
|
|
|
[99] = NULL, |
49
|
|
|
|
|
|
|
}; |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
const char* const DATE_GETTER_FROM_IX[] = { |
52
|
|
|
|
|
|
|
"toString", |
53
|
|
|
|
|
|
|
"toUTCString", |
54
|
|
|
|
|
|
|
"toGMTString", |
55
|
|
|
|
|
|
|
"toISOString", |
56
|
|
|
|
|
|
|
"toDateString", |
57
|
|
|
|
|
|
|
"toTimeString", |
58
|
|
|
|
|
|
|
"toLocaleString", |
59
|
|
|
|
|
|
|
"toLocaleDateString", |
60
|
|
|
|
|
|
|
"toLocaleTimeString", |
61
|
|
|
|
|
|
|
"getTimezoneOffset", |
62
|
|
|
|
|
|
|
"getTime", |
63
|
|
|
|
|
|
|
"getFullYear", |
64
|
|
|
|
|
|
|
"getUTCFullYear", |
65
|
|
|
|
|
|
|
"getMonth", |
66
|
|
|
|
|
|
|
"getUTCMonth", |
67
|
|
|
|
|
|
|
"getDate", |
68
|
|
|
|
|
|
|
"getUTCDate", |
69
|
|
|
|
|
|
|
"getHours", |
70
|
|
|
|
|
|
|
"getUTCHours", |
71
|
|
|
|
|
|
|
"getMinutes", |
72
|
|
|
|
|
|
|
"getUTCMinutes", |
73
|
|
|
|
|
|
|
"getSeconds", |
74
|
|
|
|
|
|
|
"getUTCSeconds", |
75
|
|
|
|
|
|
|
"getMilliseconds", |
76
|
|
|
|
|
|
|
"getUTCMilliseconds", |
77
|
|
|
|
|
|
|
"getDay", |
78
|
|
|
|
|
|
|
"getUTCDay", |
79
|
|
|
|
|
|
|
"toJSON", |
80
|
|
|
|
|
|
|
}; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
const char* const DATE_SETTER_FROM_IX[] = { |
83
|
|
|
|
|
|
|
"setTime", |
84
|
|
|
|
|
|
|
"setMilliseconds", |
85
|
|
|
|
|
|
|
"setUTCMilliseconds", |
86
|
|
|
|
|
|
|
"setSeconds", |
87
|
|
|
|
|
|
|
"setUTCSeconds", |
88
|
|
|
|
|
|
|
"setMinutes", |
89
|
|
|
|
|
|
|
"setUTCMinutes", |
90
|
|
|
|
|
|
|
"setHours", |
91
|
|
|
|
|
|
|
"setUTCHours", |
92
|
|
|
|
|
|
|
"setDate", |
93
|
|
|
|
|
|
|
"setUTCDate", |
94
|
|
|
|
|
|
|
"setMonth", |
95
|
|
|
|
|
|
|
"setUTCMonth", |
96
|
|
|
|
|
|
|
"setFullYear", |
97
|
|
|
|
|
|
|
"setUTCFullYear", |
98
|
|
|
|
|
|
|
}; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
#if defined _WIN32 || defined __CYGWIN__ |
101
|
|
|
|
|
|
|
# define PATH_SEPARATOR '\\' |
102
|
|
|
|
|
|
|
#else |
103
|
|
|
|
|
|
|
# define PATH_SEPARATOR '/' |
104
|
|
|
|
|
|
|
#endif |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
#define _jstype_name(typenum) __jstype_name_back[ typenum - JS_TAG_FIRST ] |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
static SV* _JSValue_to_SV (pTHX_ JSContext* ctx, JSValue jsval, SV** err_svp); |
109
|
|
|
|
|
|
|
|
110
|
3
|
|
|
|
|
|
static inline SV* _JSValue_special_object_to_SV (pTHX_ JSContext* ctx, JSValue jsval, SV** err_svp, const char* class) { |
111
|
|
|
|
|
|
|
assert(!*err_svp); |
112
|
|
|
|
|
|
|
|
113
|
3
|
|
|
|
|
|
SV* sv = exs_new_structref(perl_qjs_jsobj_s, class); |
114
|
3
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(sv); |
115
|
|
|
|
|
|
|
|
116
|
3
|
|
|
|
|
|
*pqjs = (perl_qjs_jsobj_s) { |
117
|
|
|
|
|
|
|
.ctx = ctx, |
118
|
3
|
|
|
|
|
|
.jsobj = JS_DupValue(ctx, jsval), |
119
|
3
|
|
|
|
|
|
.pid = getpid(), |
120
|
|
|
|
|
|
|
}; |
121
|
|
|
|
|
|
|
|
122
|
3
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
123
|
3
|
|
|
|
|
|
ctxdata->refcount++; |
124
|
|
|
|
|
|
|
|
125
|
3
|
|
|
|
|
|
return sv; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
12
|
|
|
|
|
|
static inline SV* _JSValue_object_to_SV (pTHX_ JSContext* ctx, JSValue jsval, SV** err_svp) { |
129
|
|
|
|
|
|
|
assert(!*err_svp); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
JSPropertyEnum *tab_atom; |
132
|
|
|
|
|
|
|
uint32_t tab_atom_count; |
133
|
|
|
|
|
|
|
|
134
|
12
|
|
|
|
|
|
int propnameserr = JS_GetOwnPropertyNames(ctx, &tab_atom, &tab_atom_count, jsval, JS_GPN_STRING_MASK); |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
PERL_UNUSED_VAR(propnameserr); |
137
|
|
|
|
|
|
|
assert(!propnameserr); |
138
|
|
|
|
|
|
|
|
139
|
12
|
|
|
|
|
|
HV* hv = newHV(); |
140
|
|
|
|
|
|
|
|
141
|
1247
|
100
|
|
|
|
|
for(int i = 0; i < tab_atom_count; i++) { |
142
|
1236
|
|
|
|
|
|
JSValue key = JS_AtomToString(ctx, tab_atom[i].atom); |
143
|
|
|
|
|
|
|
STRLEN strlen; |
144
|
1236
|
|
|
|
|
|
const char* keystr = JS_ToCStringLen(ctx, &strlen, key); |
145
|
|
|
|
|
|
|
|
146
|
1236
|
|
|
|
|
|
JSValue value = JS_GetProperty(ctx, jsval, tab_atom[i].atom); |
147
|
|
|
|
|
|
|
|
148
|
1236
|
|
|
|
|
|
SV* val_sv = _JSValue_to_SV(aTHX_ ctx, value, err_svp); |
149
|
|
|
|
|
|
|
|
150
|
1236
|
100
|
|
|
|
|
if (val_sv) { |
151
|
1235
|
|
|
|
|
|
hv_store(hv, keystr, -strlen, val_sv, 0); |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
1236
|
|
|
|
|
|
JS_FreeCString(ctx, keystr); |
155
|
1236
|
|
|
|
|
|
JS_FreeValue(ctx, key); |
156
|
1236
|
|
|
|
|
|
JS_FreeValue(ctx, value); |
157
|
1236
|
|
|
|
|
|
JS_FreeAtom(ctx, tab_atom[i].atom); |
158
|
|
|
|
|
|
|
|
159
|
1236
|
100
|
|
|
|
|
if (!val_sv) break; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
12
|
|
|
|
|
|
js_free(ctx, tab_atom); |
163
|
|
|
|
|
|
|
|
164
|
12
|
100
|
|
|
|
|
if (*err_svp) { |
165
|
1
|
|
|
|
|
|
SvREFCNT_dec( (SV*) hv ); |
166
|
1
|
|
|
|
|
|
return NULL; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
12
|
|
|
|
|
|
return newRV_noinc((SV*) hv); |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
23
|
|
|
|
|
|
static inline SV* _JSValue_array_to_SV (pTHX_ JSContext* ctx, JSValue jsval, SV** err_svp) { |
173
|
23
|
|
|
|
|
|
JSValue jslen = JS_GetPropertyStr(ctx, jsval, "length"); |
174
|
|
|
|
|
|
|
uint32_t len; |
175
|
23
|
|
|
|
|
|
JS_ToUint32(ctx, &len, jslen); |
176
|
23
|
|
|
|
|
|
JS_FreeValue(ctx, jslen); |
177
|
|
|
|
|
|
|
|
178
|
23
|
|
|
|
|
|
AV* av = newAV(); |
179
|
|
|
|
|
|
|
|
180
|
23
|
100
|
|
|
|
|
if (len) { |
181
|
18
|
|
|
|
|
|
av_fill( av, len - 1 ); |
182
|
48
|
100
|
|
|
|
|
for (uint32_t i=0; i
|
183
|
31
|
|
|
|
|
|
JSValue jsitem = JS_GetPropertyUint32(ctx, jsval, i); |
184
|
|
|
|
|
|
|
|
185
|
31
|
|
|
|
|
|
SV* val_sv = _JSValue_to_SV(aTHX_ ctx, jsitem, err_svp); |
186
|
|
|
|
|
|
|
|
187
|
31
|
100
|
|
|
|
|
if (val_sv) av_store( av, i, val_sv ); |
188
|
|
|
|
|
|
|
|
189
|
31
|
|
|
|
|
|
JS_FreeValue(ctx, jsitem); |
190
|
|
|
|
|
|
|
|
191
|
31
|
100
|
|
|
|
|
if (!val_sv) break; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
23
|
100
|
|
|
|
|
if (*err_svp) { |
196
|
1
|
|
|
|
|
|
SvREFCNT_dec((SV*) av); |
197
|
1
|
|
|
|
|
|
return NULL; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
23
|
|
|
|
|
|
return newRV_noinc((SV*) av); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
/* NO JS exceptions allowed here! */ |
204
|
1505
|
|
|
|
|
|
static SV* _JSValue_to_SV (pTHX_ JSContext* ctx, JSValue jsval, SV** err_svp) { |
205
|
|
|
|
|
|
|
assert(!*err_svp); |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
SV* RETVAL; |
208
|
|
|
|
|
|
|
|
209
|
1505
|
|
|
|
|
|
int tag = JS_VALUE_GET_NORM_TAG(jsval); |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
assert(tag != JS_TAG_EXCEPTION); |
212
|
|
|
|
|
|
|
|
213
|
1505
|
|
|
|
|
|
switch (tag) { |
214
|
|
|
|
|
|
|
case JS_TAG_STRING: |
215
|
|
|
|
|
|
|
STMT_START { |
216
|
|
|
|
|
|
|
STRLEN strlen; |
217
|
1050
|
|
|
|
|
|
const char* str = JS_ToCStringLen(ctx, &strlen, jsval); |
218
|
1050
|
|
|
|
|
|
RETVAL = newSVpvn_flags(str, strlen, SVf_UTF8); |
219
|
1050
|
|
|
|
|
|
JS_FreeCString(ctx, str); |
220
|
|
|
|
|
|
|
} STMT_END; |
221
|
1050
|
|
|
|
|
|
break; |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
case JS_TAG_INT: |
224
|
116
|
|
|
|
|
|
RETVAL = newSViv(JS_VALUE_GET_INT(jsval)); |
225
|
116
|
|
|
|
|
|
break; |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
case JS_TAG_FLOAT64: |
228
|
54
|
|
|
|
|
|
RETVAL = newSVnv(JS_VALUE_GET_FLOAT64(jsval)); |
229
|
54
|
|
|
|
|
|
break; |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
case JS_TAG_BOOL: |
232
|
11
|
100
|
|
|
|
|
RETVAL = boolSV(JS_VALUE_GET_BOOL(jsval)); |
233
|
11
|
|
|
|
|
|
break; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
case JS_TAG_NULL: |
236
|
|
|
|
|
|
|
case JS_TAG_UNDEFINED: |
237
|
223
|
|
|
|
|
|
RETVAL = &PL_sv_undef; |
238
|
223
|
|
|
|
|
|
break; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
case JS_TAG_OBJECT: |
241
|
47
|
100
|
|
|
|
|
if (JS_IsFunction(ctx, jsval)) { |
242
|
9
|
|
|
|
|
|
load_module( |
243
|
|
|
|
|
|
|
PERL_LOADMOD_NOIMPORT, |
244
|
|
|
|
|
|
|
newSVpvs(PQJS_FUNCTION_CLASS), |
245
|
|
|
|
|
|
|
NULL |
246
|
|
|
|
|
|
|
); |
247
|
|
|
|
|
|
|
|
248
|
9
|
|
|
|
|
|
SV* func_sv = exs_new_structref(perl_qjs_jsobj_s, PQJS_FUNCTION_CLASS); |
249
|
9
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(func_sv); |
250
|
|
|
|
|
|
|
|
251
|
9
|
|
|
|
|
|
*pqjs = (perl_qjs_jsobj_s) { |
252
|
|
|
|
|
|
|
.ctx = ctx, |
253
|
9
|
|
|
|
|
|
.jsobj = JS_DupValue(ctx, jsval), |
254
|
9
|
|
|
|
|
|
.pid = getpid(), |
255
|
|
|
|
|
|
|
}; |
256
|
|
|
|
|
|
|
|
257
|
9
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
258
|
9
|
|
|
|
|
|
ctxdata->refcount++; |
259
|
|
|
|
|
|
|
|
260
|
9
|
|
|
|
|
|
RETVAL = func_sv; |
261
|
|
|
|
|
|
|
} |
262
|
38
|
100
|
|
|
|
|
else if (JS_IsArray(ctx, jsval)) { |
263
|
23
|
|
|
|
|
|
RETVAL = _JSValue_array_to_SV(aTHX_ ctx, jsval, err_svp); |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
else { |
266
|
|
|
|
|
|
|
|
267
|
15
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
268
|
|
|
|
|
|
|
|
269
|
15
|
100
|
|
|
|
|
if (JS_IsInstanceOf(ctx, jsval, ctxdata->regexp_jsvalue)) { |
270
|
2
|
|
|
|
|
|
RETVAL = _JSValue_special_object_to_SV(aTHX_ ctx, jsval, err_svp, PQJS_REGEXP_CLASS); |
271
|
|
|
|
|
|
|
} |
272
|
13
|
100
|
|
|
|
|
else if (JS_IsInstanceOf(ctx, jsval, ctxdata->date_jsvalue)) { |
273
|
1
|
|
|
|
|
|
RETVAL = _JSValue_special_object_to_SV(aTHX_ ctx, jsval, err_svp, PQJS_DATE_CLASS); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
else { |
276
|
12
|
|
|
|
|
|
RETVAL = _JSValue_object_to_SV(aTHX_ ctx, jsval, err_svp); |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
47
|
|
|
|
|
|
break; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
default: |
283
|
|
|
|
|
|
|
STMT_START { |
284
|
4
|
|
|
|
|
|
const char* typename = _jstype_name(tag); |
285
|
|
|
|
|
|
|
|
286
|
4
|
50
|
|
|
|
|
if (typename) { |
287
|
4
|
|
|
|
|
|
*err_svp = newSVpvf("Cannot convert JS %s (QuickJS tag %d) to Perl!", typename, tag); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
else { |
290
|
0
|
|
|
|
|
|
*err_svp = newSVpvf("Cannot convert (unexpected) JS tag value %d to Perl!", tag); |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
4
|
|
|
|
|
|
return NULL; |
294
|
|
|
|
|
|
|
} STMT_END; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
1501
|
|
|
|
|
|
return RETVAL; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
16
|
|
|
|
|
|
static inline void _ctx_add_sv(pTHX_ JSContext* ctx, SV* sv) { |
301
|
16
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
302
|
|
|
|
|
|
|
|
303
|
16
|
|
|
|
|
|
ctxdata->svs_count++; |
304
|
|
|
|
|
|
|
|
305
|
16
|
100
|
|
|
|
|
if (ctxdata->svs_count == 1) { |
306
|
12
|
50
|
|
|
|
|
Newx(ctxdata->svs, ctxdata->svs_count, SV*); |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
else { |
309
|
4
|
50
|
|
|
|
|
Renew(ctxdata->svs, ctxdata->svs_count, SV*); |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
16
|
|
|
|
|
|
ctxdata->svs[ctxdata->svs_count - 1] = SvREFCNT_inc(sv); |
313
|
16
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
static JSValue _sv_to_jsvalue(pTHX_ JSContext* ctx, SV* value, SV** error); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
#define _MAX_ERRSV_TO_JS_TRIES 10 |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
/* Kind of like _sv_to_jsvalue(), but we need to handle the case where |
320
|
|
|
|
|
|
|
the error SV’s own conversion to a JSValue fails. In that case, we |
321
|
|
|
|
|
|
|
warn on the 1st error, then propagate the 2nd. Repeat until there are |
322
|
|
|
|
|
|
|
no errors. |
323
|
|
|
|
|
|
|
*/ |
324
|
8
|
|
|
|
|
|
static JSValue _sv_error_to_jsvalue(pTHX_ JSContext* ctx, SV* error) { |
325
|
8
|
|
|
|
|
|
SV* error2 = NULL; |
326
|
|
|
|
|
|
|
|
327
|
8
|
|
|
|
|
|
uint32_t tries = 0; |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
JSValue to_js; |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
while (1) { |
332
|
9
|
|
|
|
|
|
to_js = _sv_to_jsvalue(aTHX_ ctx, error, &error2); |
333
|
|
|
|
|
|
|
|
334
|
9
|
100
|
|
|
|
|
if (!error2) break; |
335
|
|
|
|
|
|
|
|
336
|
1
|
|
|
|
|
|
warn_sv(error); |
337
|
|
|
|
|
|
|
|
338
|
1
|
|
|
|
|
|
tries++; |
339
|
1
|
50
|
|
|
|
|
if (tries > _MAX_ERRSV_TO_JS_TRIES) { |
340
|
0
|
|
|
|
|
|
warn_sv(error2); |
341
|
0
|
|
|
|
|
|
return JS_NewString(ctx, "Failed to convert Perl error to JavaScript after " STRINGIFY(_MAX_ERRSV_TO_JS_TRIES) " tries!"); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
1
|
|
|
|
|
|
error = error2; |
345
|
1
|
|
|
|
|
|
error2 = NULL; |
346
|
1
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
8
|
|
|
|
|
|
return to_js; |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
15
|
|
|
|
|
|
static JSValue __do_perl_callback(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int jsmagic, JSValue *func_data) { |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
#ifdef MULTIPLICITY |
354
|
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
355
|
|
|
|
|
|
|
pTHX = ctxdata->aTHX; |
356
|
|
|
|
|
|
|
#endif |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
PERL_UNUSED_VAR(jsmagic); |
359
|
15
|
|
|
|
|
|
SV* cb_sv = ((SV**) func_data)[0]; |
360
|
|
|
|
|
|
|
|
361
|
15
|
|
|
|
|
|
SV* args[argc + 1]; |
362
|
15
|
|
|
|
|
|
args[argc] = NULL; |
363
|
|
|
|
|
|
|
|
364
|
15
|
|
|
|
|
|
SV* error_sv = NULL; |
365
|
|
|
|
|
|
|
|
366
|
25
|
100
|
|
|
|
|
for (int a=0; a
|
367
|
12
|
|
|
|
|
|
args[a] = _JSValue_to_SV(aTHX_ ctx, argv[a], &error_sv); |
368
|
|
|
|
|
|
|
|
369
|
12
|
100
|
|
|
|
|
if (error_sv) { |
370
|
3
|
100
|
|
|
|
|
while (--a >= 0) { |
371
|
1
|
|
|
|
|
|
SvREFCNT_dec(args[a]); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
2
|
|
|
|
|
|
break; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
15
|
100
|
|
|
|
|
if (!error_sv) { |
379
|
13
|
|
|
|
|
|
SV* from_perl = exs_call_sv_scalar_trapped(cb_sv, args, &error_sv); |
380
|
|
|
|
|
|
|
|
381
|
13
|
100
|
|
|
|
|
if (from_perl) { |
382
|
12
|
|
|
|
|
|
JSValue to_js = _sv_to_jsvalue(aTHX_ ctx, from_perl, &error_sv); |
383
|
|
|
|
|
|
|
|
384
|
12
|
|
|
|
|
|
sv_2mortal(from_perl); |
385
|
|
|
|
|
|
|
|
386
|
12
|
100
|
|
|
|
|
if (!error_sv) return to_js; |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
6
|
|
|
|
|
|
JSValue jserr = _sv_error_to_jsvalue(aTHX_ ctx, error_sv); |
391
|
|
|
|
|
|
|
|
392
|
15
|
|
|
|
|
|
return JS_Throw(ctx, jserr); |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
98
|
|
|
|
|
|
static JSValue _sviv_to_js(pTHX_ JSContext* ctx, SV* value) { |
396
|
|
|
|
|
|
|
if (sizeof(IV) == sizeof(int64_t)) { |
397
|
98
|
100
|
|
|
|
|
return JS_NewInt64(ctx, (int64_t) SvIV(value)); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
return JS_NewInt32(ctx, (int32_t) SvIV(value)); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
1320
|
|
|
|
|
|
static JSValue _sv_to_jsvalue(pTHX_ JSContext* ctx, SV* value, SV** error_svp) { |
404
|
1320
|
100
|
|
|
|
|
SvGETMAGIC(value); |
|
|
50
|
|
|
|
|
|
405
|
|
|
|
|
|
|
|
406
|
1320
|
100
|
|
|
|
|
switch ( exs_sv_type(value) ) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
407
|
|
|
|
|
|
|
case EXS_SVTYPE_UNDEF: |
408
|
226
|
|
|
|
|
|
return JS_NULL; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
case EXS_SVTYPE_BOOLEAN: |
411
|
0
|
0
|
|
|
|
|
return JS_NewBool(ctx, SvTRUE(value)); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
case EXS_SVTYPE_STRING: STMT_START { |
414
|
|
|
|
|
|
|
STRLEN len; |
415
|
1027
|
100
|
|
|
|
|
const char* str = SvPVutf8(value, len); |
416
|
|
|
|
|
|
|
|
417
|
1027
|
|
|
|
|
|
return JS_NewStringLen(ctx, str, len); |
418
|
|
|
|
|
|
|
} STMT_END; |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
case EXS_SVTYPE_UV: STMT_START { |
421
|
0
|
0
|
|
|
|
|
UV val_uv = SvUV(value); |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
if (sizeof(UV) == sizeof(uint64_t)) { |
424
|
0
|
0
|
|
|
|
|
if (val_uv > IV_MAX) { |
425
|
0
|
|
|
|
|
|
return JS_NewFloat64(ctx, val_uv); |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
else { |
428
|
0
|
|
|
|
|
|
return JS_NewInt64(ctx, (int64_t) val_uv); |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
else { |
432
|
|
|
|
|
|
|
return JS_NewUint32(ctx, (uint32_t) val_uv); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
} STMT_END; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
case EXS_SVTYPE_IV: STMT_START { |
437
|
21
|
|
|
|
|
|
return _sviv_to_js(aTHX_ ctx, value); |
438
|
|
|
|
|
|
|
} STMT_END; |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
case EXS_SVTYPE_NV: STMT_START { |
441
|
8
|
50
|
|
|
|
|
return JS_NewFloat64(ctx, (double) SvNV(value)); |
442
|
|
|
|
|
|
|
} STMT_END; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
case EXS_SVTYPE_REFERENCE: |
445
|
42
|
100
|
|
|
|
|
if (sv_isobject(value)) { |
446
|
10
|
100
|
|
|
|
|
if (sv_derived_from(value, PERL_BOOLEAN_CLASS)) { |
447
|
4
|
50
|
|
|
|
|
return JS_NewBool(ctx, SvTRUE(SvRV(value))); |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
448
|
|
|
|
|
|
|
} |
449
|
8
|
100
|
|
|
|
|
else if (sv_derived_from(value, PQJS_JSOBJECT_CLASS)) { |
450
|
3
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(value); |
451
|
|
|
|
|
|
|
|
452
|
3
|
100
|
|
|
|
|
if (LIKELY(pqjs->ctx == ctx)) { |
453
|
2
|
|
|
|
|
|
return JS_DupValue(ctx, pqjs->jsobj); |
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
1
|
|
|
|
|
|
*error_svp = newSVpvf("%s for QuickJS %p given to QuickJS %p!", sv_reftype(SvRV(value), 1), pqjs->ctx, ctx); |
457
|
1
|
|
|
|
|
|
return JS_NULL; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
5
|
|
|
|
|
|
break; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
32
|
|
|
|
|
|
switch (SvTYPE(SvRV(value))) { |
464
|
|
|
|
|
|
|
case SVt_PVCV: |
465
|
16
|
|
|
|
|
|
_ctx_add_sv(aTHX_ ctx, value); |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
/* A hack to store our callback via the func_data pointer: */ |
468
|
16
|
|
|
|
|
|
JSValue dummy = JS_MKPTR(JS_TAG_INT, value); |
469
|
|
|
|
|
|
|
|
470
|
31
|
|
|
|
|
|
return JS_NewCFunctionData( |
471
|
|
|
|
|
|
|
ctx, |
472
|
|
|
|
|
|
|
__do_perl_callback, |
473
|
|
|
|
|
|
|
0, 0, |
474
|
|
|
|
|
|
|
1, &dummy |
475
|
|
|
|
|
|
|
); |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
case SVt_PVAV: STMT_START { |
478
|
7
|
|
|
|
|
|
AV* av = (AV*) SvRV(value); |
479
|
7
|
|
|
|
|
|
JSValue jsarray = JS_NewArray(ctx); |
480
|
14
|
|
|
|
|
|
JS_SetPropertyStr(ctx, jsarray, "length", JS_NewUint32(ctx, 1 + av_len(av))); |
481
|
|
|
|
|
|
|
|
482
|
11
|
100
|
|
|
|
|
for (int32_t i=0; i <= av_len(av); i++) { |
483
|
5
|
|
|
|
|
|
SV** svp = av_fetch(av, i, 0); |
484
|
|
|
|
|
|
|
assert(svp); |
485
|
|
|
|
|
|
|
assert(*svp); |
486
|
|
|
|
|
|
|
|
487
|
5
|
|
|
|
|
|
JSValue jsval = _sv_to_jsvalue(aTHX_ ctx, *svp, error_svp); |
488
|
|
|
|
|
|
|
|
489
|
5
|
100
|
|
|
|
|
if (*error_svp) { |
490
|
1
|
|
|
|
|
|
JS_FreeValue(ctx, jsarray); |
491
|
1
|
|
|
|
|
|
return _sv_error_to_jsvalue(aTHX_ ctx, *error_svp); |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
4
|
|
|
|
|
|
JS_SetPropertyUint32(ctx, jsarray, i, jsval); |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
7
|
|
|
|
|
|
return jsarray; |
498
|
|
|
|
|
|
|
} STMT_END; |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
case SVt_PVHV: STMT_START { |
501
|
8
|
|
|
|
|
|
HV* hv = (HV*) SvRV(value); |
502
|
8
|
|
|
|
|
|
JSValue jsobj = JS_NewObject(ctx); |
503
|
|
|
|
|
|
|
|
504
|
8
|
|
|
|
|
|
hv_iterinit(hv); |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
HE* hvent; |
507
|
1238
|
100
|
|
|
|
|
while ( (hvent = hv_iternext(hv)) ) { |
508
|
1231
|
|
|
|
|
|
SV* key_sv = hv_iterkeysv(hvent); |
509
|
1231
|
|
|
|
|
|
SV* val_sv = hv_iterval(hv, hvent); |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
STRLEN keylen; |
512
|
1231
|
100
|
|
|
|
|
const char* key = SvPVutf8(key_sv, keylen); |
513
|
|
|
|
|
|
|
|
514
|
1231
|
|
|
|
|
|
JSValue jsval = _sv_to_jsvalue(aTHX_ ctx, val_sv, error_svp); |
515
|
1231
|
100
|
|
|
|
|
if (*error_svp) { |
516
|
1
|
|
|
|
|
|
JS_FreeValue(ctx, jsobj); |
517
|
1
|
|
|
|
|
|
return _sv_error_to_jsvalue(aTHX_ ctx, *error_svp); |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
1230
|
|
|
|
|
|
JSAtom prop = JS_NewAtomLen(ctx, key, keylen); |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
/* NB: ctx takes over jsval. */ |
523
|
1230
|
|
|
|
|
|
JS_DefinePropertyValue(ctx, jsobj, prop, jsval, JS_PROP_WRITABLE); |
524
|
|
|
|
|
|
|
|
525
|
1230
|
|
|
|
|
|
JS_FreeAtom(ctx, prop); |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
8
|
|
|
|
|
|
return jsobj; |
529
|
|
|
|
|
|
|
} STMT_END; |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
default: |
532
|
1
|
|
|
|
|
|
break; |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
default: |
536
|
1
|
|
|
|
|
|
break; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
6
|
|
|
|
|
|
*error_svp = newSVpvf("Cannot convert %" SVf " to JavaScript!", value); |
540
|
|
|
|
|
|
|
|
541
|
6
|
|
|
|
|
|
return JS_NULL; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
33
|
|
|
|
|
|
static JSContext* _create_new_jsctx( pTHX_ JSRuntime *rt ) { |
545
|
33
|
|
|
|
|
|
JSContext *ctx = JS_NewContext(rt); |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
ctx_opaque_s* ctxdata; |
548
|
33
|
|
|
|
|
|
Newxz(ctxdata, 1, ctx_opaque_s); |
549
|
33
|
|
|
|
|
|
JS_SetContextOpaque(ctx, ctxdata); |
550
|
|
|
|
|
|
|
|
551
|
33
|
|
|
|
|
|
JSValue global = JS_GetGlobalObject(ctx); |
552
|
|
|
|
|
|
|
|
553
|
33
|
|
|
|
|
|
*ctxdata = (ctx_opaque_s) { |
554
|
|
|
|
|
|
|
.refcount = 1, |
555
|
33
|
|
|
|
|
|
.regexp_jsvalue = JS_GetPropertyStr(ctx, global, "RegExp"), |
556
|
33
|
|
|
|
|
|
.date_jsvalue = JS_GetPropertyStr(ctx, global, "Date"), |
557
|
|
|
|
|
|
|
#ifdef MULTIPLICITY |
558
|
|
|
|
|
|
|
.aTHX = aTHX, |
559
|
|
|
|
|
|
|
#endif |
560
|
|
|
|
|
|
|
}; |
561
|
|
|
|
|
|
|
|
562
|
33
|
|
|
|
|
|
JS_FreeValue(ctx, global); |
563
|
|
|
|
|
|
|
|
564
|
33
|
|
|
|
|
|
return ctx; |
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
|
567
|
224
|
|
|
|
|
|
static inline SV* _return_jsvalue_or_croak(pTHX_ JSContext* ctx, JSValue jsret) { |
568
|
|
|
|
|
|
|
SV* err; |
569
|
|
|
|
|
|
|
SV* RETVAL; |
570
|
|
|
|
|
|
|
|
571
|
224
|
100
|
|
|
|
|
if (JS_IsException(jsret)) { |
572
|
10
|
|
|
|
|
|
JSValue jserr = JS_GetException(ctx); |
573
|
|
|
|
|
|
|
//err = _JSValue_to_SV(aTHX_ ctx, jserr); |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
/* Ideal here is to capture all aspects of the error object, |
576
|
|
|
|
|
|
|
including its `name` and members. But for now just give |
577
|
|
|
|
|
|
|
a string. |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
JSValue jslen = JS_GetPropertyStr(ctx, jserr, "name"); |
580
|
|
|
|
|
|
|
STRLEN namelen; |
581
|
|
|
|
|
|
|
const char* namestr = JS_ToCStringLen(ctx, &namelen, jslen); |
582
|
|
|
|
|
|
|
*/ |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
STRLEN strlen; |
585
|
10
|
|
|
|
|
|
const char* str = JS_ToCStringLen(ctx, &strlen, jserr); |
586
|
|
|
|
|
|
|
|
587
|
10
|
|
|
|
|
|
err = newSVpvn_flags(str, strlen, SVf_UTF8); |
588
|
|
|
|
|
|
|
|
589
|
10
|
|
|
|
|
|
JS_FreeCString(ctx, str); |
590
|
10
|
|
|
|
|
|
JS_FreeValue(ctx, jserr); |
591
|
10
|
|
|
|
|
|
RETVAL = NULL; // silence uninitialized warning |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
else { |
594
|
214
|
|
|
|
|
|
err = NULL; |
595
|
214
|
|
|
|
|
|
RETVAL = _JSValue_to_SV(aTHX_ ctx, jsret, &err); |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
224
|
|
|
|
|
|
JS_FreeValue(ctx, jsret); |
599
|
|
|
|
|
|
|
|
600
|
224
|
100
|
|
|
|
|
if (err) croak_sv(err); |
601
|
|
|
|
|
|
|
|
602
|
212
|
|
|
|
|
|
return RETVAL; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
44
|
|
|
|
|
|
static void _free_jsctx(pTHX_ JSContext* ctx) { |
606
|
44
|
|
|
|
|
|
ctx_opaque_s* ctxdata = JS_GetContextOpaque(ctx); |
607
|
|
|
|
|
|
|
|
608
|
44
|
100
|
|
|
|
|
if (--ctxdata->refcount == 0) { |
609
|
32
|
|
|
|
|
|
JS_FreeValue(ctx, ctxdata->regexp_jsvalue); |
610
|
32
|
|
|
|
|
|
JS_FreeValue(ctx, ctxdata->date_jsvalue); |
611
|
|
|
|
|
|
|
|
612
|
32
|
|
|
|
|
|
JSRuntime *rt = JS_GetRuntime(ctx); |
613
|
|
|
|
|
|
|
|
614
|
48
|
100
|
|
|
|
|
for (U32 i=0; isvs_count; i++) { |
615
|
16
|
|
|
|
|
|
SvREFCNT_dec(ctxdata->svs[i]); |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
32
|
|
|
|
|
|
Safefree(ctxdata); |
619
|
|
|
|
|
|
|
|
620
|
32
|
|
|
|
|
|
JS_FreeContext(ctx); |
621
|
32
|
|
|
|
|
|
JS_FreeRuntime(rt); |
622
|
|
|
|
|
|
|
} |
623
|
44
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
6
|
|
|
|
|
|
static JSModuleDef *pqjs_module_loader(JSContext *ctx, |
626
|
|
|
|
|
|
|
const char *module_name, void *opaque) { |
627
|
6
|
|
|
|
|
|
char** module_base_path_p = (char**) opaque; |
628
|
|
|
|
|
|
|
|
629
|
6
|
|
|
|
|
|
char* module_base_path = *module_base_path_p; |
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
JSModuleDef *moduledef; |
632
|
|
|
|
|
|
|
|
633
|
6
|
100
|
|
|
|
|
if (module_base_path) { |
634
|
1
|
|
|
|
|
|
size_t base_path_len = strlen(module_base_path); |
635
|
1
|
|
|
|
|
|
size_t module_name_len = strlen(module_name); |
636
|
|
|
|
|
|
|
|
637
|
1
|
|
|
|
|
|
char real_path[1 + base_path_len + module_name_len]; |
638
|
|
|
|
|
|
|
|
639
|
1
|
|
|
|
|
|
memcpy(real_path, module_base_path, base_path_len); |
640
|
1
|
|
|
|
|
|
memcpy(real_path + base_path_len, module_name, module_name_len); |
641
|
1
|
|
|
|
|
|
real_path[base_path_len + module_name_len] = 0; |
642
|
|
|
|
|
|
|
|
643
|
1
|
|
|
|
|
|
moduledef = js_module_loader(ctx, real_path, NULL); |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
else { |
646
|
5
|
|
|
|
|
|
moduledef = js_module_loader(ctx, module_name, NULL); |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
|
649
|
6
|
|
|
|
|
|
return moduledef; |
650
|
|
|
|
|
|
|
} |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
/* These must correlate to the ALIAS values below. */ |
653
|
|
|
|
|
|
|
static const char* _REGEXP_ACCESSORS[] = { |
654
|
|
|
|
|
|
|
"flags", |
655
|
|
|
|
|
|
|
"dotAll", |
656
|
|
|
|
|
|
|
"global", |
657
|
|
|
|
|
|
|
"hasIndices", |
658
|
|
|
|
|
|
|
"ignoreCase", |
659
|
|
|
|
|
|
|
"multiline", |
660
|
|
|
|
|
|
|
"source", |
661
|
|
|
|
|
|
|
"sticky", |
662
|
|
|
|
|
|
|
"unicode", |
663
|
|
|
|
|
|
|
"lastIndex", |
664
|
|
|
|
|
|
|
}; |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
/* These must correlate to the ALIAS values below. */ |
667
|
|
|
|
|
|
|
static const char* _FUNCTION_ACCESSORS[] = { |
668
|
|
|
|
|
|
|
"length", |
669
|
|
|
|
|
|
|
"name", |
670
|
|
|
|
|
|
|
}; |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
#define FUNC_CALL_INITIAL_ARGS 2 |
673
|
|
|
|
|
|
|
|
674
|
9
|
|
|
|
|
|
void _svs_to_jsvars(pTHX_ JSContext* jsctx, int32_t params_count, SV** svs, JSValue* jsvars) { |
675
|
9
|
|
|
|
|
|
SV* error = NULL; |
676
|
|
|
|
|
|
|
|
677
|
17
|
100
|
|
|
|
|
for (int32_t i=0; i
|
678
|
9
|
|
|
|
|
|
SV* cur_sv = svs[i]; |
679
|
|
|
|
|
|
|
|
680
|
9
|
|
|
|
|
|
JSValue jsval = _sv_to_jsvalue(aTHX_ jsctx, cur_sv, &error); |
681
|
|
|
|
|
|
|
|
682
|
9
|
100
|
|
|
|
|
if (error) { |
683
|
1
|
50
|
|
|
|
|
while (--i >= 0) { |
684
|
0
|
|
|
|
|
|
JS_FreeValue(jsctx, jsvars[i]); |
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
|
687
|
1
|
|
|
|
|
|
croak_sv(error); |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
8
|
|
|
|
|
|
jsvars[i] = jsval; |
691
|
|
|
|
|
|
|
} |
692
|
8
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------- */ |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
MODULE = JavaScript::QuickJS PACKAGE = JavaScript::QuickJS |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
PROTOTYPES: DISABLE |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
SV* |
701
|
|
|
|
|
|
|
_new (SV* classname_sv) |
702
|
|
|
|
|
|
|
CODE: |
703
|
33
|
|
|
|
|
|
JSRuntime *rt = JS_NewRuntime(); |
704
|
33
|
|
|
|
|
|
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL); |
705
|
33
|
|
|
|
|
|
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); |
706
|
|
|
|
|
|
|
|
707
|
33
|
|
|
|
|
|
JSContext *ctx = _create_new_jsctx(aTHX_ rt); |
708
|
|
|
|
|
|
|
|
709
|
33
|
50
|
|
|
|
|
RETVAL = exs_new_structref(perl_qjs_s, SvPVbyte_nolen(classname_sv)); |
710
|
33
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(RETVAL); |
711
|
|
|
|
|
|
|
|
712
|
33
|
|
|
|
|
|
*pqjs = (perl_qjs_s) { |
713
|
|
|
|
|
|
|
.ctx = ctx, |
714
|
33
|
|
|
|
|
|
.pid = getpid(), |
715
|
|
|
|
|
|
|
}; |
716
|
|
|
|
|
|
|
|
717
|
33
|
|
|
|
|
|
JS_SetModuleLoaderFunc( |
718
|
|
|
|
|
|
|
rt, |
719
|
|
|
|
|
|
|
NULL, |
720
|
|
|
|
|
|
|
pqjs_module_loader, |
721
|
33
|
|
|
|
|
|
&pqjs->module_base_path |
722
|
|
|
|
|
|
|
); |
723
|
|
|
|
|
|
|
|
724
|
33
|
|
|
|
|
|
JS_SetRuntimeInfo(rt, PERL_NS_ROOT); |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
OUTPUT: |
727
|
|
|
|
|
|
|
RETVAL |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
void |
730
|
|
|
|
|
|
|
DESTROY (SV* self_sv) |
731
|
|
|
|
|
|
|
CODE: |
732
|
33
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
733
|
|
|
|
|
|
|
|
734
|
33
|
50
|
|
|
|
|
if (PL_dirty && pqjs->pid == getpid()) { |
|
|
0
|
|
|
|
|
|
735
|
0
|
|
|
|
|
|
warn("DESTROYing %" SVf " at global destruction; memory leak likely!\n", self_sv); |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
33
|
100
|
|
|
|
|
if (pqjs->module_base_path) Safefree(pqjs->module_base_path); |
739
|
|
|
|
|
|
|
|
740
|
33
|
|
|
|
|
|
_free_jsctx(aTHX_ pqjs->ctx); |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
SV* |
743
|
|
|
|
|
|
|
_configure (SV* self_sv, SV* max_stack_size_sv, SV* memory_limit_sv, SV* gc_threshold_sv) |
744
|
|
|
|
|
|
|
CODE: |
745
|
8
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
746
|
|
|
|
|
|
|
|
747
|
8
|
|
|
|
|
|
JSRuntime *rt = JS_GetRuntime(pqjs->ctx); |
748
|
|
|
|
|
|
|
|
749
|
8
|
100
|
|
|
|
|
if (SvOK(max_stack_size_sv)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
750
|
4
|
|
|
|
|
|
JS_SetMaxStackSize(rt, exs_SvUV(max_stack_size_sv)); |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
|
753
|
6
|
100
|
|
|
|
|
if (SvOK(memory_limit_sv)) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
754
|
4
|
|
|
|
|
|
JS_SetMemoryLimit(rt, exs_SvUV(memory_limit_sv)); |
755
|
|
|
|
|
|
|
} |
756
|
|
|
|
|
|
|
|
757
|
4
|
50
|
|
|
|
|
if (SvOK(gc_threshold_sv)) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
758
|
4
|
|
|
|
|
|
JS_SetGCThreshold(rt, exs_SvUV(gc_threshold_sv)); |
759
|
|
|
|
|
|
|
} |
760
|
|
|
|
|
|
|
|
761
|
2
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
OUTPUT: |
764
|
|
|
|
|
|
|
RETVAL |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
SV* |
767
|
|
|
|
|
|
|
std (SV* self_sv) |
768
|
|
|
|
|
|
|
ALIAS: |
769
|
|
|
|
|
|
|
os = 1 |
770
|
|
|
|
|
|
|
helpers = 2 |
771
|
|
|
|
|
|
|
CODE: |
772
|
2
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
773
|
|
|
|
|
|
|
|
774
|
2
|
|
|
|
|
|
switch (ix) { |
775
|
|
|
|
|
|
|
case 0: |
776
|
1
|
|
|
|
|
|
js_init_module_std(pqjs->ctx, "std"); |
777
|
1
|
|
|
|
|
|
break; |
778
|
|
|
|
|
|
|
case 1: |
779
|
0
|
|
|
|
|
|
js_init_module_os(pqjs->ctx, "os"); |
780
|
0
|
|
|
|
|
|
break; |
781
|
|
|
|
|
|
|
case 2: |
782
|
1
|
|
|
|
|
|
js_std_add_helpers(pqjs->ctx, 0, NULL); |
783
|
1
|
|
|
|
|
|
break; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
default: |
786
|
0
|
|
|
|
|
|
croak("%s: Bad XS alias: %d\n", __func__, (int) ix); |
787
|
|
|
|
|
|
|
} |
788
|
|
|
|
|
|
|
|
789
|
2
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
OUTPUT: |
792
|
|
|
|
|
|
|
RETVAL |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
SV* |
795
|
|
|
|
|
|
|
unset_module_base (SV* self_sv) |
796
|
|
|
|
|
|
|
CODE: |
797
|
1
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
798
|
|
|
|
|
|
|
|
799
|
1
|
50
|
|
|
|
|
if (pqjs->module_base_path) { |
800
|
0
|
|
|
|
|
|
Safefree(pqjs->module_base_path); |
801
|
0
|
|
|
|
|
|
pqjs->module_base_path = NULL; |
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
|
804
|
1
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
805
|
|
|
|
|
|
|
OUTPUT: |
806
|
|
|
|
|
|
|
RETVAL |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
SV* |
809
|
|
|
|
|
|
|
set_module_base (SV* self_sv, SV* path_sv) |
810
|
|
|
|
|
|
|
CODE: |
811
|
1
|
50
|
|
|
|
|
if (!SvOK(path_sv)) croak("Give a path! (Did you want unset_module_base?)"); |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
812
|
|
|
|
|
|
|
|
813
|
1
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
814
|
|
|
|
|
|
|
|
815
|
1
|
|
|
|
|
|
const char* path = exs_SvPVbyte_nolen(path_sv); |
816
|
|
|
|
|
|
|
|
817
|
1
|
|
|
|
|
|
size_t path_len = strlen(path); |
818
|
|
|
|
|
|
|
|
819
|
1
|
50
|
|
|
|
|
if (pqjs->module_base_path) { |
820
|
0
|
|
|
|
|
|
Renew(pqjs->module_base_path, 2 + path_len, char); |
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
else { |
823
|
1
|
|
|
|
|
|
Newx(pqjs->module_base_path, 2 + path_len, char); |
824
|
|
|
|
|
|
|
} |
825
|
|
|
|
|
|
|
|
826
|
1
|
|
|
|
|
|
Copy(path, pqjs->module_base_path, 2 + path_len, char); |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
/** If the given path is “/foo/bar”, we store “/foo/bar/”. |
829
|
|
|
|
|
|
|
This means if “/foo/bar/” is given we store “/foo/bar//”, |
830
|
|
|
|
|
|
|
which is ugly but should work on all supported platforms. |
831
|
|
|
|
|
|
|
*/ |
832
|
1
|
|
|
|
|
|
pqjs->module_base_path[path_len] = PATH_SEPARATOR; |
833
|
1
|
|
|
|
|
|
pqjs->module_base_path[1 + path_len] = 0; |
834
|
|
|
|
|
|
|
|
835
|
1
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
836
|
|
|
|
|
|
|
OUTPUT: |
837
|
|
|
|
|
|
|
RETVAL |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
SV* |
840
|
|
|
|
|
|
|
set_globals (SV* self_sv, ...) |
841
|
|
|
|
|
|
|
CODE: |
842
|
40
|
50
|
|
|
|
|
if (items < 2) croak("Need at least 1 key/value pair."); |
843
|
|
|
|
|
|
|
|
844
|
40
|
50
|
|
|
|
|
if (!(items % 2)) croak("Need an even list of key/value pairs."); |
845
|
|
|
|
|
|
|
|
846
|
40
|
|
|
|
|
|
I32 valscount = (items - 1) >> 1; |
847
|
|
|
|
|
|
|
|
848
|
40
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
SV* jsname_sv, *value_sv; |
851
|
|
|
|
|
|
|
|
852
|
40
|
|
|
|
|
|
SV* error = NULL; |
853
|
|
|
|
|
|
|
|
854
|
40
|
|
|
|
|
|
JSAtom jsnames[valscount]; |
855
|
40
|
|
|
|
|
|
JSValue jsvals[valscount]; |
856
|
|
|
|
|
|
|
|
857
|
83
|
100
|
|
|
|
|
for (int i=0; i < valscount; i++) { |
858
|
45
|
|
|
|
|
|
jsname_sv = ST( 1 + (i << 1) ); |
859
|
45
|
|
|
|
|
|
value_sv = ST( 2 + (i << 1) ); |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
STRLEN jsnamelen; |
862
|
45
|
100
|
|
|
|
|
const char* jsname_str = SvPVutf8(jsname_sv, jsnamelen); |
863
|
|
|
|
|
|
|
|
864
|
45
|
|
|
|
|
|
JSValue jsval = _sv_to_jsvalue(aTHX_ pqjs->ctx, value_sv, &error); |
865
|
|
|
|
|
|
|
|
866
|
45
|
100
|
|
|
|
|
if (error) { |
867
|
2
|
50
|
|
|
|
|
while (i-- > 0) { |
868
|
0
|
|
|
|
|
|
JS_FreeAtom(pqjs->ctx, jsnames[i]); |
869
|
0
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, jsvals[i]); |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
|
872
|
2
|
|
|
|
|
|
croak_sv(error); |
873
|
|
|
|
|
|
|
} |
874
|
|
|
|
|
|
|
|
875
|
43
|
|
|
|
|
|
jsnames[i] = JS_NewAtomLen(pqjs->ctx, jsname_str, jsnamelen); |
876
|
43
|
|
|
|
|
|
jsvals[i] = jsval; |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
38
|
|
|
|
|
|
JSValue jsglobal = JS_GetGlobalObject(pqjs->ctx); |
880
|
|
|
|
|
|
|
|
881
|
81
|
100
|
|
|
|
|
for (int i=0; i < valscount; i++) { |
882
|
|
|
|
|
|
|
/* NB: ctx takes over jsval. */ |
883
|
43
|
|
|
|
|
|
JS_DefinePropertyValue(pqjs->ctx, jsglobal, jsnames[i], jsvals[i], JS_PROP_WRITABLE); |
884
|
43
|
|
|
|
|
|
JS_FreeAtom(pqjs->ctx, jsnames[i]); |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
38
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, jsglobal); |
888
|
|
|
|
|
|
|
|
889
|
38
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
OUTPUT: |
892
|
|
|
|
|
|
|
RETVAL |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
SV* |
895
|
|
|
|
|
|
|
eval (SV* self_sv, SV* js_code_sv) |
896
|
|
|
|
|
|
|
ALIAS: |
897
|
|
|
|
|
|
|
eval_module = 1 |
898
|
|
|
|
|
|
|
CODE: |
899
|
114
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
900
|
114
|
|
|
|
|
|
JSContext *ctx = pqjs->ctx; |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
STRLEN js_code_len; |
903
|
114
|
100
|
|
|
|
|
const char* js_code = SvPVutf8(js_code_sv, js_code_len); |
904
|
|
|
|
|
|
|
|
905
|
114
|
|
|
|
|
|
int eval_flags = ix ? JS_EVAL_TYPE_MODULE : JS_EVAL_TYPE_GLOBAL; |
906
|
114
|
|
|
|
|
|
eval_flags |= JS_EVAL_FLAG_STRICT; |
907
|
|
|
|
|
|
|
|
908
|
114
|
|
|
|
|
|
JSValue jsret = JS_Eval(ctx, js_code, js_code_len, "", eval_flags); |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
// In eval_module()’s case we want to croak if there was |
911
|
|
|
|
|
|
|
// an exception. If not we’ll just discard the return value |
912
|
114
|
|
|
|
|
|
RETVAL = _return_jsvalue_or_croak(aTHX_ ctx, jsret); |
913
|
|
|
|
|
|
|
|
914
|
102
|
100
|
|
|
|
|
if (ix) { |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
// The only thing a JS module should return is null. |
917
|
|
|
|
|
|
|
// If that’s ever not the case, warn: |
918
|
3
|
50
|
|
|
|
|
if ( UNLIKELY(RETVAL != &PL_sv_undef) ) { |
919
|
0
|
|
|
|
|
|
warn("UNEXPECTED: Discarding non-null return from ES module: %" SVf, RETVAL); |
920
|
0
|
|
|
|
|
|
SvREFCNT_dec(RETVAL); |
921
|
|
|
|
|
|
|
} |
922
|
|
|
|
|
|
|
|
923
|
3
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
924
|
|
|
|
|
|
|
} |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
OUTPUT: |
927
|
|
|
|
|
|
|
RETVAL |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
SV* |
930
|
|
|
|
|
|
|
await (SV* self_sv) |
931
|
|
|
|
|
|
|
CODE: |
932
|
2
|
|
|
|
|
|
perl_qjs_s* pqjs = exs_structref_ptr(self_sv); |
933
|
2
|
|
|
|
|
|
JSContext *ctx = pqjs->ctx; |
934
|
|
|
|
|
|
|
|
935
|
2
|
|
|
|
|
|
js_std_loop(ctx); |
936
|
|
|
|
|
|
|
|
937
|
2
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
OUTPUT: |
940
|
|
|
|
|
|
|
RETVAL |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
MODULE = JavaScript::QuickJS PACKAGE = JavaScript::QuickJS::Date |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
SV* |
947
|
|
|
|
|
|
|
setTime (SV* self_sv, SV* num_sv) |
948
|
|
|
|
|
|
|
ALIAS: |
949
|
|
|
|
|
|
|
setMilliseconds = 1 |
950
|
|
|
|
|
|
|
setUTCMilliseconds = 2 |
951
|
|
|
|
|
|
|
setSeconds = 3 |
952
|
|
|
|
|
|
|
setUTCSeconds = 4 |
953
|
|
|
|
|
|
|
setMinutes = 5 |
954
|
|
|
|
|
|
|
setUTCMinutes = 6 |
955
|
|
|
|
|
|
|
setHours = 7 |
956
|
|
|
|
|
|
|
setUTCHours = 8 |
957
|
|
|
|
|
|
|
setDate = 9 |
958
|
|
|
|
|
|
|
setUTCDate = 10 |
959
|
|
|
|
|
|
|
setMonth = 11 |
960
|
|
|
|
|
|
|
setUTCMonth = 12 |
961
|
|
|
|
|
|
|
setFullYear = 13 |
962
|
|
|
|
|
|
|
setUTCFullYear = 14 |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
CODE: |
965
|
28
|
|
|
|
|
|
const char* setter_name = DATE_SETTER_FROM_IX[ix]; |
966
|
|
|
|
|
|
|
|
967
|
28
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
968
|
28
|
|
|
|
|
|
JSContext *ctx = pqjs->ctx; |
969
|
|
|
|
|
|
|
|
970
|
28
|
|
|
|
|
|
JSAtom prop = JS_NewAtom(ctx, setter_name); |
971
|
28
|
|
|
|
|
|
JSValue arg = _sviv_to_js(aTHX_ ctx, num_sv); |
972
|
|
|
|
|
|
|
|
973
|
28
|
|
|
|
|
|
JSValue jsret = JS_Invoke( |
974
|
|
|
|
|
|
|
ctx, |
975
|
|
|
|
|
|
|
pqjs->jsobj, |
976
|
|
|
|
|
|
|
prop, |
977
|
|
|
|
|
|
|
1, |
978
|
|
|
|
|
|
|
&arg |
979
|
|
|
|
|
|
|
); |
980
|
|
|
|
|
|
|
|
981
|
28
|
|
|
|
|
|
JS_FreeAtom(ctx, prop); |
982
|
28
|
|
|
|
|
|
JS_FreeValue(ctx, arg); |
983
|
|
|
|
|
|
|
|
984
|
28
|
|
|
|
|
|
RETVAL = _return_jsvalue_or_croak(aTHX_ pqjs->ctx, jsret); |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
OUTPUT: |
987
|
|
|
|
|
|
|
RETVAL |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
SV* |
990
|
|
|
|
|
|
|
toString (SV* self_sv, ...) |
991
|
|
|
|
|
|
|
ALIAS: |
992
|
|
|
|
|
|
|
toUTCString = 1 |
993
|
|
|
|
|
|
|
toGMTString = 2 |
994
|
|
|
|
|
|
|
toISOString = 3 |
995
|
|
|
|
|
|
|
toDateString = 4 |
996
|
|
|
|
|
|
|
toTimeString = 5 |
997
|
|
|
|
|
|
|
toLocaleString = 6 |
998
|
|
|
|
|
|
|
toLocaleDateString = 7 |
999
|
|
|
|
|
|
|
toLocaleTimeString = 8 |
1000
|
|
|
|
|
|
|
getTimezoneOffset = 9 |
1001
|
|
|
|
|
|
|
getTime = 10 |
1002
|
|
|
|
|
|
|
getFullYear = 11 |
1003
|
|
|
|
|
|
|
getUTCFullYear = 12 |
1004
|
|
|
|
|
|
|
getMonth = 13 |
1005
|
|
|
|
|
|
|
getUTCMonth = 14 |
1006
|
|
|
|
|
|
|
getDate = 15 |
1007
|
|
|
|
|
|
|
getUTCDate = 16 |
1008
|
|
|
|
|
|
|
getHours = 17 |
1009
|
|
|
|
|
|
|
getUTCHours = 18 |
1010
|
|
|
|
|
|
|
getMinutes = 19 |
1011
|
|
|
|
|
|
|
getUTCMinutes = 20 |
1012
|
|
|
|
|
|
|
getSeconds = 21 |
1013
|
|
|
|
|
|
|
getUTCSeconds = 22 |
1014
|
|
|
|
|
|
|
getMilliseconds = 23 |
1015
|
|
|
|
|
|
|
getUTCMilliseconds = 24 |
1016
|
|
|
|
|
|
|
getDay = 25 |
1017
|
|
|
|
|
|
|
getUTCDay = 26 |
1018
|
|
|
|
|
|
|
toJSON = 27 |
1019
|
|
|
|
|
|
|
CODE: |
1020
|
70
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1021
|
70
|
|
|
|
|
|
JSContext *ctx = pqjs->ctx; |
1022
|
|
|
|
|
|
|
|
1023
|
70
|
|
|
|
|
|
JSAtom prop = JS_NewAtom(ctx, DATE_GETTER_FROM_IX[ix]); |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
JSValue jsret; |
1026
|
|
|
|
|
|
|
|
1027
|
70
|
50
|
|
|
|
|
if (items > 1) { |
1028
|
0
|
|
|
|
|
|
int params_count = items - 1; |
1029
|
|
|
|
|
|
|
|
1030
|
0
|
|
|
|
|
|
JSValue jsargs[params_count]; |
1031
|
|
|
|
|
|
|
|
1032
|
0
|
|
|
|
|
|
_svs_to_jsvars(aTHX_ ctx, params_count, &ST(1), jsargs); |
1033
|
|
|
|
|
|
|
|
1034
|
0
|
|
|
|
|
|
jsret = JS_Invoke( |
1035
|
|
|
|
|
|
|
ctx, |
1036
|
|
|
|
|
|
|
pqjs->jsobj, |
1037
|
|
|
|
|
|
|
prop, |
1038
|
|
|
|
|
|
|
params_count, |
1039
|
0
|
|
|
|
|
|
jsargs |
1040
|
|
|
|
|
|
|
); |
1041
|
|
|
|
|
|
|
|
1042
|
0
|
0
|
|
|
|
|
for (uint32_t i=0; i
|
1043
|
0
|
|
|
|
|
|
JS_FreeValue(ctx, jsargs[i]); |
1044
|
|
|
|
|
|
|
} |
1045
|
|
|
|
|
|
|
} |
1046
|
|
|
|
|
|
|
else { |
1047
|
70
|
|
|
|
|
|
jsret = JS_Invoke( |
1048
|
|
|
|
|
|
|
ctx, |
1049
|
|
|
|
|
|
|
pqjs->jsobj, |
1050
|
|
|
|
|
|
|
prop, |
1051
|
|
|
|
|
|
|
0, |
1052
|
|
|
|
|
|
|
NULL |
1053
|
|
|
|
|
|
|
); |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
|
1056
|
70
|
|
|
|
|
|
JS_FreeAtom(ctx, prop); |
1057
|
|
|
|
|
|
|
|
1058
|
70
|
|
|
|
|
|
RETVAL = _return_jsvalue_or_croak(aTHX_ pqjs->ctx, jsret); |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
OUTPUT: |
1061
|
|
|
|
|
|
|
RETVAL |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
MODULE = JavaScript::QuickJS PACKAGE = JavaScript::QuickJS::RegExp |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
SV* |
1068
|
|
|
|
|
|
|
exec (SV* self_sv, SV* specimen_sv) |
1069
|
|
|
|
|
|
|
ALIAS: |
1070
|
|
|
|
|
|
|
test = 1 |
1071
|
|
|
|
|
|
|
CODE: |
1072
|
4
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1073
|
4
|
|
|
|
|
|
JSContext *ctx = pqjs->ctx; |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
STRLEN specimen_len; |
1076
|
4
|
50
|
|
|
|
|
const char* specimen = SvPVutf8(specimen_sv, specimen_len); |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
/* TODO: optimize? */ |
1079
|
4
|
100
|
|
|
|
|
JSAtom prop = JS_NewAtom(ctx, ix ? "test" : "exec"); |
1080
|
|
|
|
|
|
|
|
1081
|
4
|
|
|
|
|
|
JSValue specimen_js = JS_NewStringLen(ctx, specimen, specimen_len); |
1082
|
|
|
|
|
|
|
|
1083
|
4
|
|
|
|
|
|
JSValue jsret = JS_Invoke( |
1084
|
|
|
|
|
|
|
ctx, |
1085
|
|
|
|
|
|
|
pqjs->jsobj, |
1086
|
|
|
|
|
|
|
prop, |
1087
|
|
|
|
|
|
|
1, |
1088
|
|
|
|
|
|
|
&specimen_js |
1089
|
|
|
|
|
|
|
); |
1090
|
|
|
|
|
|
|
|
1091
|
4
|
|
|
|
|
|
JS_FreeValue(ctx, specimen_js); |
1092
|
4
|
|
|
|
|
|
JS_FreeAtom(ctx, prop); |
1093
|
|
|
|
|
|
|
|
1094
|
4
|
|
|
|
|
|
RETVAL = _return_jsvalue_or_croak(aTHX_ pqjs->ctx, jsret); |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
OUTPUT: |
1097
|
|
|
|
|
|
|
RETVAL |
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
SV* |
1100
|
|
|
|
|
|
|
flags( SV* self_sv) |
1101
|
|
|
|
|
|
|
ALIAS: |
1102
|
|
|
|
|
|
|
dotAll = 1 |
1103
|
|
|
|
|
|
|
global = 2 |
1104
|
|
|
|
|
|
|
hasIndices = 3 |
1105
|
|
|
|
|
|
|
ignoreCase = 4 |
1106
|
|
|
|
|
|
|
multiline = 5 |
1107
|
|
|
|
|
|
|
source = 6 |
1108
|
|
|
|
|
|
|
sticky = 7 |
1109
|
|
|
|
|
|
|
unicode = 8 |
1110
|
|
|
|
|
|
|
lastIndex = 9 |
1111
|
|
|
|
|
|
|
CODE: |
1112
|
8
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1113
|
|
|
|
|
|
|
|
1114
|
8
|
|
|
|
|
|
JSValue myret = JS_GetPropertyStr(pqjs->ctx, pqjs->jsobj, _REGEXP_ACCESSORS[ix]); |
1115
|
|
|
|
|
|
|
|
1116
|
8
|
|
|
|
|
|
SV* err = NULL; |
1117
|
|
|
|
|
|
|
|
1118
|
8
|
|
|
|
|
|
RETVAL = _JSValue_to_SV(aTHX_ pqjs->ctx, myret, &err); |
1119
|
|
|
|
|
|
|
|
1120
|
8
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, myret); |
1121
|
|
|
|
|
|
|
|
1122
|
8
|
50
|
|
|
|
|
if (err) croak_sv(err); |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
OUTPUT: |
1125
|
|
|
|
|
|
|
RETVAL |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
MODULE = JavaScript::QuickJS PACKAGE = JavaScript::QuickJS::JSObject |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
void |
1132
|
|
|
|
|
|
|
DESTROY( SV* self_sv ) |
1133
|
|
|
|
|
|
|
CODE: |
1134
|
11
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1135
|
|
|
|
|
|
|
|
1136
|
11
|
50
|
|
|
|
|
if (PL_dirty && pqjs->pid == getpid()) { |
|
|
0
|
|
|
|
|
|
1137
|
0
|
|
|
|
|
|
warn("DESTROYing %" SVf " at global destruction; memory leak likely!\n", self_sv); |
1138
|
|
|
|
|
|
|
} |
1139
|
|
|
|
|
|
|
|
1140
|
11
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, pqjs->jsobj); |
1141
|
|
|
|
|
|
|
|
1142
|
11
|
|
|
|
|
|
_free_jsctx(aTHX_ pqjs->ctx); |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
# ---------------------------------------------------------------------- |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
MODULE = JavaScript::QuickJS PACKAGE = JavaScript::QuickJS::Function |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
SV* |
1149
|
|
|
|
|
|
|
_give_self( SV* self_sv, ... ) |
1150
|
|
|
|
|
|
|
CODE: |
1151
|
1
|
|
|
|
|
|
RETVAL = SvREFCNT_inc(self_sv); |
1152
|
|
|
|
|
|
|
OUTPUT: |
1153
|
|
|
|
|
|
|
RETVAL |
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
SV* |
1156
|
|
|
|
|
|
|
length( SV* self_sv) |
1157
|
|
|
|
|
|
|
ALIAS: |
1158
|
|
|
|
|
|
|
name = 1 |
1159
|
|
|
|
|
|
|
CODE: |
1160
|
4
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1161
|
|
|
|
|
|
|
|
1162
|
4
|
|
|
|
|
|
JSValue myret = JS_GetPropertyStr(pqjs->ctx, pqjs->jsobj, _FUNCTION_ACCESSORS[ix]); |
1163
|
|
|
|
|
|
|
|
1164
|
4
|
|
|
|
|
|
SV* err = NULL; |
1165
|
|
|
|
|
|
|
|
1166
|
4
|
|
|
|
|
|
RETVAL = _JSValue_to_SV(aTHX_ pqjs->ctx, myret, &err); |
1167
|
|
|
|
|
|
|
|
1168
|
4
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, myret); |
1169
|
|
|
|
|
|
|
|
1170
|
4
|
50
|
|
|
|
|
if (err) croak_sv(err); |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
OUTPUT: |
1173
|
|
|
|
|
|
|
RETVAL |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
SV* |
1176
|
|
|
|
|
|
|
call( SV* self_sv, SV* this_sv=&PL_sv_undef, ... ) |
1177
|
|
|
|
|
|
|
CODE: |
1178
|
9
|
|
|
|
|
|
perl_qjs_jsobj_s* pqjs = exs_structref_ptr(self_sv); |
1179
|
|
|
|
|
|
|
|
1180
|
9
|
|
|
|
|
|
U32 params_count = items - FUNC_CALL_INITIAL_ARGS; |
1181
|
|
|
|
|
|
|
|
1182
|
9
|
|
|
|
|
|
SV* error = NULL; |
1183
|
|
|
|
|
|
|
|
1184
|
9
|
|
|
|
|
|
JSValue thisjs = _sv_to_jsvalue(aTHX_ pqjs->ctx, this_sv, &error); |
1185
|
9
|
50
|
|
|
|
|
if (error) croak_sv(error); |
1186
|
|
|
|
|
|
|
|
1187
|
9
|
|
|
|
|
|
JSValue jsvars[params_count]; |
1188
|
|
|
|
|
|
|
|
1189
|
9
|
|
|
|
|
|
_svs_to_jsvars( aTHX_ pqjs->ctx, params_count, &ST(FUNC_CALL_INITIAL_ARGS), jsvars ); |
1190
|
|
|
|
|
|
|
|
1191
|
8
|
|
|
|
|
|
JSValue jsret = JS_Call(pqjs->ctx, pqjs->jsobj, thisjs, params_count, jsvars); |
1192
|
|
|
|
|
|
|
|
1193
|
8
|
|
|
|
|
|
RETVAL = _return_jsvalue_or_croak(aTHX_ pqjs->ctx, jsret); |
1194
|
|
|
|
|
|
|
|
1195
|
8
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, thisjs); |
1196
|
|
|
|
|
|
|
|
1197
|
16
|
100
|
|
|
|
|
for (uint32_t i=0; i
|
1198
|
8
|
|
|
|
|
|
JS_FreeValue(pqjs->ctx, jsvars[i]); |
1199
|
|
|
|
|
|
|
} |
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
OUTPUT: |
1202
|
|
|
|
|
|
|
RETVAL |