@@ -38212,40 +38212,75 @@ static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
38212
38212
JSValue str;
38213
38213
JSValue ret;
38214
38214
JSString *p;
38215
- uint32_t i, n, hi, lo ;
38215
+ uint32_t c, i, n ;
38216
38216
38217
38217
ret = JS_TRUE;
38218
38218
str = JS_ToStringCheckObject(ctx, this_val);
38219
38219
if (JS_IsException(str))
38220
38220
return JS_EXCEPTION;
38221
38221
38222
38222
p = JS_VALUE_GET_STRING(str);
38223
- if (p->is_wide_char) {
38224
- for (i = 0, n = p->len; i < n; i++) {
38225
- hi = p->u.str16[i];
38226
- if (hi < 0xD800 || hi > 0xDFFF)
38227
- continue;
38228
- if (hi > 0xDBFF) {
38229
- ret = JS_FALSE;
38230
- break;
38231
- }
38232
- i++;
38233
- if (i == n) {
38234
- ret = JS_FALSE;
38235
- break;
38236
- }
38237
- lo = p->u.str16[i];
38238
- if (lo < 0xDC00 || lo > 0xDFFF) {
38239
- ret = JS_FALSE;
38240
- break;
38241
- }
38242
- }
38223
+ if (!p->is_wide_char || p->len == 0)
38224
+ goto done; // by definition well-formed
38225
+
38226
+ for (i = 0, n = p->len; i < n; i++) {
38227
+ c = p->u.str16[i];
38228
+ if (c < 0xD800 || c > 0xDFFF)
38229
+ continue;
38230
+ if (c > 0xDBFF || i+1 == n)
38231
+ break;
38232
+ c = p->u.str16[++i];
38233
+ if (c < 0xDC00 || c > 0xDFFF)
38234
+ break;
38243
38235
}
38244
38236
38237
+ if (i < n)
38238
+ ret = JS_FALSE;
38239
+
38240
+ done:
38245
38241
JS_FreeValue(ctx, str);
38246
38242
return ret;
38247
38243
}
38248
38244
38245
+ static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
38246
+ int argc, JSValueConst *argv)
38247
+ {
38248
+ JSValue str;
38249
+ JSValue ret;
38250
+ JSString *p;
38251
+ uint32_t c, i, n;
38252
+
38253
+ str = JS_ToStringCheckObject(ctx, this_val);
38254
+ if (JS_IsException(str))
38255
+ return JS_EXCEPTION;
38256
+
38257
+ p = JS_VALUE_GET_STRING(str);
38258
+ if (!p->is_wide_char || p->len == 0)
38259
+ return str; // by definition well-formed
38260
+
38261
+ // TODO(bnoordhuis) don't clone when input is well-formed
38262
+ ret = js_new_string16(ctx, p->u.str16, p->len);
38263
+ JS_FreeValue(ctx, str);
38264
+ if (JS_IsException(ret))
38265
+ return JS_EXCEPTION;
38266
+
38267
+ p = JS_VALUE_GET_STRING(ret);
38268
+ for (i = 0, n = p->len; i < n; i++) {
38269
+ c = p->u.str16[i];
38270
+ if (c < 0xD800 || c > 0xDFFF)
38271
+ continue;
38272
+ if (c > 0xDBFF || i+1 == n) {
38273
+ p->u.str16[i] = 0xFFFD;
38274
+ continue;
38275
+ }
38276
+ c = p->u.str16[++i];
38277
+ if (c < 0xDC00 || c > 0xDFFF)
38278
+ p->u.str16[--i] = 0xFFFD;
38279
+ }
38280
+
38281
+ return ret;
38282
+ }
38283
+
38249
38284
static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
38250
38285
int argc, JSValueConst *argv, int lastIndexOf)
38251
38286
{
@@ -39398,6 +39433,7 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
39398
39433
JS_CFUNC_DEF("concat", 1, js_string_concat ),
39399
39434
JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
39400
39435
JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
39436
+ JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
39401
39437
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
39402
39438
JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
39403
39439
JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),
0 commit comments