Skip to content

Commit

Permalink
NativeString: Implement isWellFormed and toWellFormed
Browse files Browse the repository at this point in the history
  • Loading branch information
camnwalter authored and gbrail committed Sep 21, 2024
1 parent 8687fc8 commit a76f06a
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 9 deletions.
8 changes: 5 additions & 3 deletions rhino/src/main/java/org/mozilla/javascript/NativeJSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,9 @@ private static String quote(String string) {
product.append("\\t");
break;
default:
if (isLeadingSurrogate(c) && i < length - 1 && isTrailingSurrogate(string.charAt(i + 1))) {
if (isLeadingSurrogate(c)
&& i < length - 1
&& isTrailingSurrogate(string.charAt(i + 1))) {
// do nothing as the next case will add both surrogates
break;
} else if (isTrailingSurrogate(c) && isLeadingSurrogate(prev)) {
Expand All @@ -569,11 +571,11 @@ private static String quote(String string) {
return product.toString();
}

private static boolean isLeadingSurrogate(char c) {
static boolean isLeadingSurrogate(char c) {
return c >= 0xD800 && c <= 0xDBFF;
}

private static boolean isTrailingSurrogate(char c) {
static boolean isTrailingSurrogate(char c) {
return c >= 0xDC00 && c <= 0xDFFF;
}

Expand Down
68 changes: 67 additions & 1 deletion rhino/src/main/java/org/mozilla/javascript/NativeString.java
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,14 @@ protected void initPrototypeId(int id) {
arity = 0;
s = "trimEnd";
break;
case Id_isWellFormed:
arity = 0;
s = "isWellFormed";
break;
case Id_toWellFormed:
arity = 0;
s = "toWellFormed";
break;
default:
throw new IllegalArgumentException(String.valueOf(id));
}
Expand Down Expand Up @@ -772,6 +780,56 @@ else if (Normalizer.Form.NFC.name().equals(formStr))

return str.substring(k, k + 1);
}
case Id_isWellFormed:
{
String str = ScriptRuntime.toString(requireObjectCoercible(cx, thisObj, f));
int len = str.length();
boolean foundLeadingSurrogate = false;
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
if (NativeJSON.isLeadingSurrogate(c)) {
if (foundLeadingSurrogate) {
return false;
}
foundLeadingSurrogate = true;
} else if (NativeJSON.isTrailingSurrogate(c)) {
if (!foundLeadingSurrogate) {
return false;
}
foundLeadingSurrogate = false;
} else if (foundLeadingSurrogate) {
return false;
}
}
return !foundLeadingSurrogate;
}
case Id_toWellFormed:
{
String str = ScriptRuntime.toString(requireObjectCoercible(cx, thisObj, f));
StringBuilder sb = new StringBuilder();
int len = str.length();
char prev = 0;
for (int i = 0; i < len; i++) {
char c = str.charAt(i);

if (NativeJSON.isLeadingSurrogate(c)
&& i < len - 1
&& NativeJSON.isTrailingSurrogate(str.charAt(i + 1))) {
// do nothing as the next case will add both surrogates
} else if (NativeJSON.isTrailingSurrogate(c)
&& NativeJSON.isLeadingSurrogate(prev)) {
sb.append(prev).append(c);
} else if (NativeJSON.isLeadingSurrogate(c)
|| NativeJSON.isTrailingSurrogate(c)) {
sb.append('\uFFFD');
} else {
sb.append(c);
}
prev = c;
}

return sb.toString();
}

case SymbolId_iterator:
return new NativeStringIterator(scope, requireObjectCoercible(cx, thisObj, f));
Expand Down Expand Up @@ -1358,6 +1416,12 @@ protected int findPrototypeId(String s) {
case "at":
id = Id_at;
break;
case "isWellFormed":
id = Id_isWellFormed;
break;
case "toWellFormed":
id = Id_toWellFormed;
break;
default:
id = 0;
break;
Expand Down Expand Up @@ -1420,7 +1484,9 @@ protected int findPrototypeId(String s) {
Id_trimStart = 50,
Id_trimEnd = 51,
Id_at = 52,
MAX_PROTOTYPE_ID = Id_at;
Id_isWellFormed = 53,
Id_toWellFormed = 54,
MAX_PROTOTYPE_ID = Id_toWellFormed;
private static final int ConstructorId_charAt = -Id_charAt,
ConstructorId_charCodeAt = -Id_charCodeAt,
ConstructorId_indexOf = -Id_indexOf,
Expand Down
11 changes: 6 additions & 5 deletions tests/testsrc/test262.properties
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ built-ins/GeneratorPrototype 38/60 (63.33%)

built-ins/Infinity 0/6 (0.0%)

built-ins/JSON 37/144 (25.69%)
built-ins/JSON 36/144 (25.0%)
parse/builtin.js {unsupported: [Reflect.construct]}
parse/duplicate-proto.js
parse/not-a-constructor.js {unsupported: [Reflect.construct]}
Expand Down Expand Up @@ -1012,7 +1012,6 @@ built-ins/JSON 37/144 (25.69%)
stringify/value-bigint-tojson-receiver.js
stringify/value-object-proxy.js {unsupported: [Proxy]}
stringify/value-object-proxy-revoked.js {unsupported: [Proxy]}
stringify/value-string-escape-unicode.js

built-ins/Map 13/171 (7.6%)
prototype/clear/not-a-constructor.js {unsupported: [Reflect.construct]}
Expand Down Expand Up @@ -2199,7 +2198,7 @@ built-ins/SetIteratorPrototype 0/11 (0.0%)

~built-ins/SharedArrayBuffer

built-ins/String 140/1182 (11.84%)
built-ins/String 128/1182 (10.83%)
fromCharCode/not-a-constructor.js {unsupported: [Reflect.construct]}
fromCodePoint/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/charAt/not-a-constructor.js {unsupported: [Reflect.construct]}
Expand All @@ -2219,7 +2218,8 @@ built-ins/String 140/1182 (11.84%)
prototype/indexOf/searchstring-tostring-errors.js
prototype/indexOf/searchstring-tostring-toprimitive.js
prototype/indexOf/searchstring-tostring-wrapped-values.js
prototype/isWellFormed 8/8 (100.0%)
prototype/isWellFormed/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/isWellFormed/to-string-primitive.js
prototype/lastIndexOf/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/localeCompare/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/matchAll 20/20 (100.0%)
Expand Down Expand Up @@ -2285,7 +2285,8 @@ built-ins/String 140/1182 (11.84%)
prototype/toString/non-generic-realm.js
prototype/toString/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/toUpperCase/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/toWellFormed 8/8 (100.0%)
prototype/toWellFormed/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/toWellFormed/to-string-primitive.js
prototype/trimEnd/not-a-constructor.js {unsupported: [Reflect.construct]}
prototype/trimEnd/this-value-object-toprimitive-call-err.js
prototype/trimEnd/this-value-object-toprimitive-meth-err.js
Expand Down

0 comments on commit a76f06a

Please sign in to comment.