Skip to content

Commit 825b216

Browse files
committed
Update QuickJS: faster context creation and faster dbuf
Update couchjs.c to use the new intrinsics return value and check their initialization. * Faster context creation and exception checks in JS_NewContext bellard/quickjs@42eb279 * Faster and safer dbuf functions bellard/quickjs@0d4cd2d * Fixed argument evaluation order in Date constructor and Date.UTC() bellard/quickjs@7fb994c * Stricter year parsing in Date bellard/quickjs@2161640
1 parent d521620 commit 825b216

File tree

12 files changed

+886
-741
lines changed

12 files changed

+886
-741
lines changed

src/couch_quickjs/c_src/couchjs.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,20 @@ static CmdType parse_command(char* str, size_t len) {
8686
return CMD_VIEW;
8787
}
8888

89-
static void add_cx_methods(JSContext* cx) {
89+
// Return true if initializations succeed and false if any fails. Failure
90+
// will shortcut the sequence and will return early. The only thing to do
91+
// then is to free the context and return early
92+
//
93+
static bool add_cx_methods(JSContext* cx) {
9094
//TODO: configure some features with env vars of command line switches
91-
JS_AddIntrinsicBaseObjects(cx);
92-
JS_AddIntrinsicEval(cx);
93-
JS_AddIntrinsicJSON(cx);
94-
JS_AddIntrinsicRegExp(cx);
95-
JS_AddIntrinsicMapSet(cx);
96-
JS_AddIntrinsicDate(cx);
95+
return ! (
96+
JS_AddIntrinsicBaseObjects(cx) ||
97+
JS_AddIntrinsicEval(cx) ||
98+
JS_AddIntrinsicJSON(cx) ||
99+
JS_AddIntrinsicRegExp(cx) ||
100+
JS_AddIntrinsicMapSet(cx) ||
101+
JS_AddIntrinsicDate(cx)
102+
);
97103
}
98104

99105
// Creates a new JSContext with only the provided sandbox function
@@ -104,7 +110,12 @@ static JSContext* make_sandbox(JSContext* cx, JSValue sbox) {
104110
if(!cx1) {
105111
return NULL;
106112
}
107-
add_cx_methods(cx1);
113+
114+
if(!add_cx_methods(cx1)) {
115+
JS_FreeContext(cx1);
116+
return NULL;
117+
}
118+
108119
JSValue global = JS_GetGlobalObject(cx1);
109120

110121
int i;

src/couch_quickjs/patches/01-spidermonkey-185-mode.patch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
--- quickjs-master/quickjs.c 2025-10-08 08:16:51
2-
+++ quickjs/quickjs.c 2025-10-08 17:43:48
3-
@@ -30951,10 +30951,24 @@
1+
--- quickjs-master/quickjs.c 2025-10-13 08:51:37
2+
+++ quickjs/quickjs.c 2025-10-15 21:57:44
3+
@@ -30997,10 +30997,24 @@
44
if (s->token.val == TOK_FUNCTION ||
55
(token_is_pseudo_keyword(s, JS_ATOM_async) &&
66
peek_token(s, TRUE) == TOK_FUNCTION)) {
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
--- quickjs-master/test262_errors.txt 2025-10-08 08:16:51
2-
+++ quickjs/test262_errors.txt 2025-10-08 17:43:48
3-
@@ -6,6 +6,8 @@
4-
test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side
1+
--- quickjs-master/test262_errors.txt 2025-10-13 08:51:37
2+
+++ quickjs/test262_errors.txt 2025-10-15 22:00:27
3+
@@ -7,6 +7,8 @@
54
test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side
65
test262/test/language/identifier-resolution/assign-to-global-undefined.js:20: strict mode: expected error
6+
test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called
77
+test262/test/language/statements/expression/S12.4_A1.js:15: unexpected error type: Test262: This statement should not be evaluated.
88
+test262/test/language/statements/expression/S12.4_A1.js:15: strict mode: unexpected error type: Test262: This statement should not be evaluated.
9-
test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true
10-
test262/test/staging/sm/Date/UTC-convert-all-arguments.js:13: strict mode: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true
11-
test262/test/staging/sm/Date/constructor-convert-all-arguments.js:13: Test262Error: index undefined: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true
9+
test262/test/staging/sm/Function/arguments-parameter-shadowing.js:14: Test262Error: Expected SameValue(«true», «false») to be true
10+
test262/test/staging/sm/Function/constructor-binding.js:11: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true
11+
test262/test/staging/sm/Function/constructor-binding.js:11: strict mode: Test262Error: Expected SameValue(«"function"», «"undefined"») to be true

src/couch_quickjs/quickjs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ PREFIX?=/usr/local
5555
#CONFIG_UBSAN=y
5656

5757
# TEST262 bootstrap config: commit id and shallow "since" parameter
58-
TEST262_COMMIT?=06dfddc4ebd21c39e1ce44f3e13b56b0dfda28e3
58+
TEST262_COMMIT?=42303c7c2bcf1c1edb9e5375c291c6fbc8a261ab
5959
TEST262_SINCE?=2025-09-01
6060

6161
OBJDIR=.obj

src/couch_quickjs/quickjs/cutils.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,20 @@ void dbuf_init(DynBuf *s)
100100
dbuf_init2(s, NULL, NULL);
101101
}
102102

103-
/* return < 0 if error */
104-
int dbuf_realloc(DynBuf *s, size_t new_size)
103+
/* Try to allocate 'len' more bytes. return < 0 if error */
104+
int dbuf_claim(DynBuf *s, size_t len)
105105
{
106-
size_t size;
106+
size_t new_size, size;
107107
uint8_t *new_buf;
108+
new_size = s->size + len;
109+
if (new_size < len)
110+
return -1; /* overflow case */
108111
if (new_size > s->allocated_size) {
109112
if (s->error)
110113
return -1;
111-
size = s->allocated_size * 3 / 2;
114+
size = s->allocated_size + (s->allocated_size / 2);
115+
if (size < s->allocated_size)
116+
return -1; /* overflow case */
112117
if (size > new_size)
113118
new_size = size;
114119
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
@@ -122,22 +127,10 @@ int dbuf_realloc(DynBuf *s, size_t new_size)
122127
return 0;
123128
}
124129

125-
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
126-
{
127-
size_t end;
128-
end = offset + len;
129-
if (dbuf_realloc(s, end))
130-
return -1;
131-
memcpy(s->buf + offset, data, len);
132-
if (end > s->size)
133-
s->size = end;
134-
return 0;
135-
}
136-
137130
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
138131
{
139-
if (unlikely((s->size + len) > s->allocated_size)) {
140-
if (dbuf_realloc(s, s->size + len))
132+
if (unlikely((s->allocated_size - s->size) < len)) {
133+
if (dbuf_claim(s, len))
141134
return -1;
142135
}
143136
memcpy_no_ub(s->buf + s->size, data, len);
@@ -147,20 +140,35 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
147140

148141
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
149142
{
150-
if (unlikely((s->size + len) > s->allocated_size)) {
151-
if (dbuf_realloc(s, s->size + len))
143+
if (unlikely((s->allocated_size - s->size) < len)) {
144+
if (dbuf_claim(s, len))
152145
return -1;
153146
}
154147
memcpy(s->buf + s->size, s->buf + offset, len);
155148
s->size += len;
156149
return 0;
157150
}
158151

159-
int dbuf_putc(DynBuf *s, uint8_t c)
152+
int __dbuf_putc(DynBuf *s, uint8_t c)
160153
{
161154
return dbuf_put(s, &c, 1);
162155
}
163156

157+
int __dbuf_put_u16(DynBuf *s, uint16_t val)
158+
{
159+
return dbuf_put(s, (uint8_t *)&val, 2);
160+
}
161+
162+
int __dbuf_put_u32(DynBuf *s, uint32_t val)
163+
{
164+
return dbuf_put(s, (uint8_t *)&val, 4);
165+
}
166+
167+
int __dbuf_put_u64(DynBuf *s, uint64_t val)
168+
{
169+
return dbuf_put(s, (uint8_t *)&val, 8);
170+
}
171+
164172
int dbuf_putstr(DynBuf *s, const char *str)
165173
{
166174
return dbuf_put(s, (const uint8_t *)str, strlen(str));
@@ -182,7 +190,7 @@ int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
182190
/* fast case */
183191
return dbuf_put(s, (uint8_t *)buf, len);
184192
} else {
185-
if (dbuf_realloc(s, s->size + len + 1))
193+
if (dbuf_claim(s, len + 1))
186194
return -1;
187195
va_start(ap, fmt);
188196
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,

src/couch_quickjs/quickjs/cutils.h

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,24 +264,58 @@ typedef struct DynBuf {
264264

265265
void dbuf_init(DynBuf *s);
266266
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
267-
int dbuf_realloc(DynBuf *s, size_t new_size);
268-
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
267+
int dbuf_claim(DynBuf *s, size_t len);
269268
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
270269
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
271-
int dbuf_putc(DynBuf *s, uint8_t c);
272270
int dbuf_putstr(DynBuf *s, const char *str);
271+
int __dbuf_putc(DynBuf *s, uint8_t c);
272+
int __dbuf_put_u16(DynBuf *s, uint16_t val);
273+
int __dbuf_put_u32(DynBuf *s, uint32_t val);
274+
int __dbuf_put_u64(DynBuf *s, uint64_t val);
275+
276+
static inline int dbuf_putc(DynBuf *s, uint8_t val)
277+
{
278+
if (unlikely((s->allocated_size - s->size) < 1)) {
279+
return __dbuf_putc(s, val);
280+
} else {
281+
s->buf[s->size++] = val;
282+
return 0;
283+
}
284+
}
285+
273286
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
274287
{
275-
return dbuf_put(s, (uint8_t *)&val, 2);
288+
if (unlikely((s->allocated_size - s->size) < 2)) {
289+
return __dbuf_put_u16(s, val);
290+
} else {
291+
put_u16(s->buf + s->size, val);
292+
s->size += 2;
293+
return 0;
294+
}
276295
}
296+
277297
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
278298
{
279-
return dbuf_put(s, (uint8_t *)&val, 4);
299+
if (unlikely((s->allocated_size - s->size) < 4)) {
300+
return __dbuf_put_u32(s, val);
301+
} else {
302+
put_u32(s->buf + s->size, val);
303+
s->size += 4;
304+
return 0;
305+
}
280306
}
307+
281308
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
282309
{
283-
return dbuf_put(s, (uint8_t *)&val, 8);
310+
if (unlikely((s->allocated_size - s->size) < 8)) {
311+
return __dbuf_put_u64(s, val);
312+
} else {
313+
put_u64(s->buf + s->size, val);
314+
s->size += 8;
315+
return 0;
316+
}
284317
}
318+
285319
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
286320
const char *fmt, ...);
287321
void dbuf_free(DynBuf *s);

src/couch_quickjs/quickjs/libregexp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static inline int is_digit(int c) {
117117
/* insert 'len' bytes at position 'pos'. Return < 0 if error. */
118118
static int dbuf_insert(DynBuf *s, int pos, int len)
119119
{
120-
if (dbuf_realloc(s, s->size + len))
120+
if (dbuf_claim(s, len))
121121
return -1;
122122
memmove(s->buf + pos + len, s->buf + pos, s->size - pos);
123123
s->size += len;
@@ -2340,7 +2340,7 @@ static int re_parse_alternative(REParseState *s, BOOL is_backward_dir)
23402340
speed is not really critical here) */
23412341
end = s->byte_code.size;
23422342
term_size = end - term_start;
2343-
if (dbuf_realloc(&s->byte_code, end + term_size))
2343+
if (dbuf_claim(&s->byte_code, term_size))
23442344
return -1;
23452345
memmove(s->byte_code.buf + start + term_size,
23462346
s->byte_code.buf + start,

src/couch_quickjs/quickjs/libunicode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
11791179
is_compat = n_type >> 1;
11801180

11811181
dbuf_init2(dbuf, opaque, realloc_func);
1182-
if (dbuf_realloc(dbuf, sizeof(int) * src_len))
1182+
if (dbuf_claim(dbuf, sizeof(int) * src_len))
11831183
goto fail;
11841184

11851185
/* common case: latin1 is unaffected by NFC */

src/couch_quickjs/quickjs/quickjs-atom.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ DEF(SyntaxError, "SyntaxError")
256256
DEF(TypeError, "TypeError")
257257
DEF(URIError, "URIError")
258258
DEF(InternalError, "InternalError")
259+
DEF(AggregateError, "AggregateError")
259260
/* private symbols */
260261
DEF(Private_brand, "<brand>")
261262
/* symbols */

0 commit comments

Comments
 (0)