Skip to content

Commit 15f4d8b

Browse files
committed
Add internal duk_concat_2() helper
1 parent c47ef78 commit 15f4d8b

3 files changed

Lines changed: 49 additions & 5 deletions

File tree

src-input/duk_api_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_context *ctx, duk_idx_t obj_idx,
308308
DUK_INTERNAL_DECL void duk_insert_undefined(duk_context *ctx, duk_idx_t idx);
309309
DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_context *ctx, duk_idx_t idx, duk_idx_t count);
310310

311+
DUK_INTERNAL_DECL void duk_concat_2(duk_context *ctx);
312+
311313
DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_context *ctx, duk_idx_t nargs, duk_small_uint_t call_flags);
312314

313315
/* Raw internal valstack access macros: access is unsafe so call site

src-input/duk_api_string.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,50 @@ DUK_EXTERNAL void duk_concat(duk_context *ctx, duk_idx_t count) {
113113
duk__concat_and_join_helper(ctx, count, 0 /*is_join*/);
114114
}
115115

116+
#if defined(DUK_USE_PREFER_SIZE)
117+
DUK_INTERNAL void duk_concat_2(duk_context *ctx) {
118+
duk_concat(ctx, 2);
119+
}
120+
#else /* DUK_USE_PREFER_SIZE */
121+
DUK_INTERNAL void duk_concat_2(duk_context *ctx) {
122+
duk_hthread *thr = (duk_hthread *) ctx;
123+
duk_hstring *h1;
124+
duk_hstring *h2;
125+
duk_uint8_t *buf;
126+
duk_size_t len1;
127+
duk_size_t len2;
128+
duk_size_t len;
129+
130+
DUK_ASSERT_CTX_VALID(ctx);
131+
DUK_ASSERT(duk_get_top(ctx) >= 2); /* Trusted caller. */
132+
133+
h1 = duk_to_hstring(ctx, -2);
134+
h2 = duk_to_hstring(ctx, -1);
135+
len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
136+
len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
137+
len = len1 + len2;
138+
if (DUK_UNLIKELY(len < len1 || /* wrapped */
139+
len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
140+
goto error_overflow;
141+
}
142+
buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(ctx, len);
143+
DUK_ASSERT(buf != NULL);
144+
145+
DUK_MEMCPY((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
146+
DUK_MEMCPY((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
147+
(void) duk_buffer_to_string(ctx, -1); /* Safe if inputs are safe. */
148+
149+
/* [ ... str1 str2 buf ] */
150+
151+
duk_replace(ctx, -3);
152+
duk_pop_unsafe(ctx);
153+
return;
154+
155+
error_overflow:
156+
DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
157+
}
158+
#endif /* DUK_USE_PREFER_SIZE */
159+
116160
DUK_EXTERNAL void duk_join(duk_context *ctx, duk_idx_t count) {
117161
DUK_ASSERT_CTX_VALID(ctx);
118162

src-input/duk_js_executor.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,10 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_add(duk_hthread *thr, duk_tval *tv
172172
/* Symbols shouldn't technically be handled here, but should
173173
* go into the default ToNumber() coercion path instead and
174174
* fail there with a TypeError. However, there's a ToString()
175-
* here which also fails with TypeError so no explicit check
176-
* is needed.
175+
* in duk_concat_2() which also fails with TypeError so no
176+
* explicit check is needed.
177177
*/
178-
duk_to_string(ctx, -2);
179-
duk_to_string(ctx, -1);
180-
duk_concat(ctx, 2); /* [... s1 s2] -> [... s1+s2] */
178+
duk_concat_2(ctx); /* [... s1 s2] -> [... s1+s2] */
181179
} else {
182180
duk_double_t d1, d2;
183181

0 commit comments

Comments
 (0)