mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:17:35 +00:00
LibJS: Evaluate replacement value before searching source string
The String.prototype.replace spec requires evaluating the replacement value (if it is not a function) before searching the source string. Fixes 4 test262 tests.
This commit is contained in:
parent
65003241e4
commit
81fec49ac3
4 changed files with 67 additions and 0 deletions
|
@ -286,6 +286,16 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
if (!replace_value.is_function()) {
|
||||||
|
auto replace_string = replace_value.to_string(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
replace_value = js_string(vm, move(replace_string));
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
auto global_value = rx->get(vm.names.global);
|
auto global_value = rx->get(vm.names.global);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -800,6 +800,17 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace)
|
||||||
auto search_string = search_value.to_string(global_object);
|
auto search_string = search_value.to_string(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
if (!replace_value.is_function()) {
|
||||||
|
auto replace_string = replace_value.to_string(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
replace_value = js_string(vm, move(replace_string));
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Optional<size_t> position = string.find(search_string);
|
Optional<size_t> position = string.find(search_string);
|
||||||
if (!position.has_value())
|
if (!position.has_value())
|
||||||
return js_string(vm, string);
|
return js_string(vm, string);
|
||||||
|
@ -877,6 +888,16 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::replace_all)
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
if (!replace_value.is_function()) {
|
||||||
|
auto replace_string = replace_value.to_string(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
replace_value = js_string(vm, move(replace_string));
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Vector<size_t> match_positions;
|
Vector<size_t> match_positions;
|
||||||
size_t advance_by = max(1u, search_string.length());
|
size_t advance_by = max(1u, search_string.length());
|
||||||
auto position = string.find(search_string);
|
auto position = string.find(search_string);
|
||||||
|
|
|
@ -158,3 +158,21 @@ test("replacement with substitution and 'groups' coerced to an object", () => {
|
||||||
|
|
||||||
expect(r[Symbol.replace]("ab", "[$<length>]")).toBe("a[3]");
|
expect(r[Symbol.replace]("ab", "[$<length>]")).toBe("a[3]");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("replacement value is evaluated before searching the source string", () => {
|
||||||
|
var calls = 0;
|
||||||
|
var replaceValue = {
|
||||||
|
toString: function () {
|
||||||
|
calls += 1;
|
||||||
|
return "b";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var newString = "".replace("a", replaceValue);
|
||||||
|
expect(newString).toBe("");
|
||||||
|
expect(calls).toBe(1);
|
||||||
|
|
||||||
|
newString = "".replace(/a/g, replaceValue);
|
||||||
|
expect(newString).toBe("");
|
||||||
|
expect(calls).toBe(2);
|
||||||
|
});
|
||||||
|
|
|
@ -104,3 +104,21 @@ test("functional regex replacement", () => {
|
||||||
})
|
})
|
||||||
).toBe("xd");
|
).toBe("xd");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("replacement value is evaluated before searching the source string", () => {
|
||||||
|
var calls = 0;
|
||||||
|
var replaceValue = {
|
||||||
|
toString: function () {
|
||||||
|
calls += 1;
|
||||||
|
return "b";
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var newString = "".replaceAll("a", replaceValue);
|
||||||
|
expect(newString).toBe("");
|
||||||
|
expect(calls).toBe(1);
|
||||||
|
|
||||||
|
newString = "".replaceAll(/a/g, replaceValue);
|
||||||
|
expect(newString).toBe("");
|
||||||
|
expect(calls).toBe(2);
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue