@@ -2011,6 +2011,116 @@ TEST_P(JSITest, DeleteProperty) {
20112011 EXPECT_TRUE (hasRes);
20122012}
20132013
2014+ TEST_P (JSITest, ArrayPush) {
2015+ // This Runtime Decorator is used to test the default implementation of
2016+ // Runtime::push
2017+ class RD : public RuntimeDecorator <Runtime, Runtime> {
2018+ public:
2019+ explicit RD (Runtime& rt) : RuntimeDecorator(rt) {}
2020+
2021+ size_t push (const Array& arr, const Value* elements, size_t count)
2022+ override {
2023+ return Runtime::push (arr, elements, count);
2024+ }
2025+ };
2026+ RD rd = RD (rt);
2027+
2028+ // Push to an empty array
2029+ Array arr (rd, 0 );
2030+ size_t newLength = arr.push (rd, 1 , 2 , 3 );
2031+ EXPECT_EQ (newLength, 3 );
2032+ EXPECT_EQ (arr.length (rd), 3 );
2033+
2034+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2035+ EXPECT_EQ (arr.getValueAtIndex (rd, 1 ).getNumber (), 2 );
2036+ EXPECT_EQ (arr.getValueAtIndex (rd, 2 ).getNumber (), 3 );
2037+
2038+ // Push to an array already containing elements
2039+ arr = Array::createWithElements (rd, 1 , true );
2040+ Object obj (rd);
2041+ newLength = arr.push (rd, " foobar" , obj);
2042+ EXPECT_EQ (newLength, 4 );
2043+ EXPECT_EQ (arr.length (rd), 4 );
2044+
2045+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2046+ EXPECT_TRUE (arr.getValueAtIndex (rd, 1 ).getBool ());
2047+ EXPECT_EQ (arr.getValueAtIndex (rd, 2 ).getString (rd).utf8 (rd), " foobar" );
2048+ EXPECT_TRUE (
2049+ Object::strictEquals (rd, arr.getValueAtIndex (rd, 3 ).getObject (rd), obj));
2050+
2051+ // Push to a Proxy of a JS Array
2052+ arr = eval (" new Proxy([1], {})" ).getObject (rd).getArray (rd);
2053+ EXPECT_EQ (arr.length (rd), 1 );
2054+
2055+ newLength = arr.push (rd, true , " foobar" );
2056+ EXPECT_EQ (newLength, 3 );
2057+ EXPECT_EQ (arr.length (rd), 3 );
2058+
2059+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2060+ EXPECT_TRUE (arr.getValueAtIndex (rd, 1 ).getBool ());
2061+ EXPECT_EQ (arr.getValueAtIndex (rd, 2 ).getString (rd).utf8 (rd), " foobar" );
2062+
2063+ // Push to a Proxy of a JS Array, where getting the length returns a custom
2064+ // value
2065+ arr = eval (
2066+ " var arr = [1];"
2067+ " var handler = {"
2068+ " get(target, property) {"
2069+ " if (property == 'length') {"
2070+ " return target.length + 1;"
2071+ " }"
2072+ " return Reflect.get(target, property);"
2073+ " }"
2074+ " };"
2075+ " var proxy = new Proxy(arr, handler);"
2076+ " proxy;" )
2077+ .getObject (rd)
2078+ .getArray (rd);
2079+ // The handler returns the underlying array's length plus 1
2080+ EXPECT_EQ (arr.length (rd), 2 );
2081+
2082+ // The elements will be adding starting at element 2
2083+ newLength = arr.push (rd, 3 , 4 );
2084+ EXPECT_EQ (newLength, 4 );
2085+
2086+ EXPECT_EQ (arr.length (rd), 5 );
2087+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2088+ EXPECT_TRUE (arr.getValueAtIndex (rd, 1 ).isUndefined ());
2089+ EXPECT_EQ (arr.getValueAtIndex (rd, 2 ).getNumber (), 3 );
2090+ EXPECT_EQ (arr.getValueAtIndex (rd, 3 ).getNumber (), 4 );
2091+
2092+ // Push to a Proxy of a JS Array, where setting the 'length' property is
2093+ // customized
2094+ arr = eval (
2095+ " var arr = [1];"
2096+ " var handler = {"
2097+ " set(target, property, value) {"
2098+ " if (property == 'length') {"
2099+ " return Reflect.set(target, property, value + 1);"
2100+ " }"
2101+ " return Reflect.set(target, property, value);"
2102+ " }"
2103+ " };"
2104+ " var proxy = new Proxy(arr, handler);"
2105+ " proxy;" )
2106+ .getObject (rd)
2107+ .getArray (rd);
2108+
2109+ EXPECT_EQ (arr.length (rd), 1 );
2110+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2111+
2112+ newLength = arr.push (rd, 2 , 3 );
2113+ EXPECT_EQ (newLength, 3 );
2114+
2115+ // When setting the 'length' property, the handler will actually set it to 3 +
2116+ // 1
2117+ EXPECT_EQ (arr.length (rd), 4 );
2118+ EXPECT_EQ (arr.getValueAtIndex (rd, 0 ).getNumber (), 1 );
2119+ EXPECT_EQ (arr.getValueAtIndex (rd, 1 ).getNumber (), 2 );
2120+ EXPECT_EQ (arr.getValueAtIndex (rd, 2 ).getNumber (), 3 );
2121+ EXPECT_TRUE (arr.getValueAtIndex (rd, 3 ).isUndefined ());
2122+ }
2123+
20142124INSTANTIATE_TEST_CASE_P (
20152125 Runtimes,
20162126 JSITest,
0 commit comments