Skip to content

Commit cfe4251

Browse files
authored
Implement String.prototype.toWellFormed (#43)
Reworks isWellFormed to be consistent style-wise with toWellFormed.
1 parent afee50e commit cfe4251

File tree

2 files changed

+58
-22
lines changed

2 files changed

+58
-22
lines changed

quickjs.c

+57-21
Original file line numberDiff line numberDiff line change
@@ -38212,40 +38212,75 @@ static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
3821238212
JSValue str;
3821338213
JSValue ret;
3821438214
JSString *p;
38215-
uint32_t i, n, hi, lo;
38215+
uint32_t c, i, n;
3821638216

3821738217
ret = JS_TRUE;
3821838218
str = JS_ToStringCheckObject(ctx, this_val);
3821938219
if (JS_IsException(str))
3822038220
return JS_EXCEPTION;
3822138221

3822238222
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;
3824338235
}
3824438236

38237+
if (i < n)
38238+
ret = JS_FALSE;
38239+
38240+
done:
3824538241
JS_FreeValue(ctx, str);
3824638242
return ret;
3824738243
}
3824838244

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+
3824938284
static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
3825038285
int argc, JSValueConst *argv, int lastIndexOf)
3825138286
{
@@ -39398,6 +39433,7 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
3939839433
JS_CFUNC_DEF("concat", 1, js_string_concat ),
3939939434
JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
3940039435
JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
39436+
JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
3940139437
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
3940239438
JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
3940339439
JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),

test262.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ String.prototype.includes
172172
String.prototype.isWellFormed
173173
String.prototype.matchAll
174174
String.prototype.replaceAll
175-
String.prototype.toWellFormed=skip
175+
String.prototype.toWellFormed
176176
String.prototype.trimEnd
177177
String.prototype.trimStart
178178
super

0 commit comments

Comments
 (0)