mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 16:21:29 +00:00
LibJS: Fix array hole and string object indexing prototype indirection
This fixes two cases of indexed access (array holes, out-of-bounds string object access) where we would not follow the prototype chain and incorrectly return undefined: // Should be "a", returned undefined Object.setPrototypeOf([,], ["a"])[0] // Should be "a", returned undefined Object.setPrototypeOf(new String(""), new String("a"))[0] The actual fix is simple, instead of returning early if the requested index is past the string's length or within the indexed properties size but has no value, we just continue the prototype chain traversal and get correct behaviour from that.
This commit is contained in:
parent
72fbf26dd6
commit
433a23cfde
Notes:
sideshowbarker
2024-07-18 20:31:18 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/433a23cfded Pull-request: https://github.com/SerenityOS/serenity/pull/6239
|
@ -751,19 +751,16 @@ Value Object::get_by_index(u32 property_index) const
|
|||
{
|
||||
const Object* object = this;
|
||||
while (object) {
|
||||
if (is<StringObject>(*this)) {
|
||||
auto& string = static_cast<const StringObject*>(this)->primitive_string().string();
|
||||
if (is<StringObject>(*object)) {
|
||||
auto& string = static_cast<const StringObject&>(*object).primitive_string().string();
|
||||
if (property_index < string.length())
|
||||
return js_string(heap(), string.substring(property_index, 1));
|
||||
return js_undefined();
|
||||
}
|
||||
if (static_cast<size_t>(property_index) < object->m_indexed_properties.array_like_size()) {
|
||||
} else if (static_cast<size_t>(property_index) < object->m_indexed_properties.array_like_size()) {
|
||||
auto result = object->m_indexed_properties.get(const_cast<Object*>(this), property_index);
|
||||
if (vm().exception())
|
||||
return {};
|
||||
if (result.has_value() && !result.value().value.is_empty())
|
||||
return result.value().value;
|
||||
return {};
|
||||
}
|
||||
object = object->prototype();
|
||||
if (vm().exception())
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
describe("normal behavior", () => {
|
||||
test("regular object indexing", () => {
|
||||
const o = {};
|
||||
const p = { 0: "foo" };
|
||||
Object.setPrototypeOf(o, p);
|
||||
expect(o[0]).toBe("foo");
|
||||
});
|
||||
|
||||
test("array object indexing", () => {
|
||||
const o = [];
|
||||
const p = ["foo"];
|
||||
Object.setPrototypeOf(o, p);
|
||||
expect(o[0]).toBe("foo");
|
||||
});
|
||||
|
||||
test("array object hole indexing", () => {
|
||||
const o = [,];
|
||||
const p = ["foo"];
|
||||
Object.setPrototypeOf(o, p);
|
||||
expect(o[0]).toBe("foo");
|
||||
});
|
||||
|
||||
test("string object indexing", () => {
|
||||
const o = new String("");
|
||||
const p = new String("a");
|
||||
Object.setPrototypeOf(o, p);
|
||||
expect(o[0]).toBe("a");
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue