v8/test/debugger/debug/side-effect/debug-evaluate-no-side-effect-builtins.js
peterwmwong 952c097679 [builtins] Port Array.p.join to Torque.
This also includes ports of Array.p.toString and Array.p.toLocaleString.
Many parts of the old JS implementation are preserved, because
TypedArray.p.join still relies on it.  These will be removed once
TypedArray.p.join is ported to Torque.

To simplify implementation, special handling of extremely sparse arrays
has been removed.

Performance improvements vary by array size, elements, and sparse-ness.
Some quick numbers and graphs are here:
https://docs.google.com/spreadsheets/d/125VLmRMudk8XaomLCsZQ1ewc94WCqht-8GQwU3s9BW8/edit#gid=2087673710

Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.v8.try:v8_linux_noi18n_rel_ng;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: Ia4069a068403ce36676c37401d349aefc976b045
Reviewed-on: https://chromium-review.googlesource.com/c/1196693
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56699}
2018-10-16 13:56:31 +00:00

234 lines
8.4 KiB
JavaScript

// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --no-enable-one-shot-optimization
Debug = debug.Debug
var exception = null;
var object_with_symbol_key = {[Symbol("a")]: 1};
var object_with_callbacks = { toString: () => "string", valueOf: () => 3};
var symbol_for_a = Symbol.for("a");
var typed_array = new Uint8Array([1, 2, 3]);
var array_buffer = new ArrayBuffer(3);
var data_view = new DataView(new ArrayBuffer(8), 0, 8);
var array = [1,2,3];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
function success(expectation, source) {
var result = exec_state.frame(0).evaluate(source, true).value();
if (expectation !== undefined) assertEquals(expectation, result);
}
function fail(source) {
assertThrows(() => exec_state.frame(0).evaluate(source, true),
EvalError);
}
// Test some Object functions.
success({}, `new Object()`);
success({p : 3}, `Object.create({}, { p: { value: 3 } })`);
success("[[\"a\",1],[\"b\",2]]",
`JSON.stringify(Object.entries({a:1, b:2}))`);
success({value: 1, writable: true, enumerable: true, configurable: true},
`Object.getOwnPropertyDescriptor({a: 1}, "a")`);
success("{\"a\":{\"value\":1,\"writable\":true," +
"\"enumerable\":true,\"configurable\":true}}",
`JSON.stringify(Object.getOwnPropertyDescriptors({a: 1}))`);
success(["a"], `Object.getOwnPropertyNames({a: 1})`);
success(undefined, `Object.getOwnPropertySymbols(object_with_symbol_key)`);
success({}, `Object.getPrototypeOf(Object.create({}))`);
success(true, `Object.is(Object, Object)`);
success(true, `Object.isExtensible({})`);
success(false, `Object.isFrozen({})`);
success(false, `Object.isSealed({})`);
success([1, 2], `Object.values({a:1, b:2})`);
fail(`Object.assign({}, {})`);
fail(`Object.defineProperties({}, [{p:{value:3}}])`);
fail(`Object.defineProperty({}, {p:{value:3}})`);
fail(`Object.freeze({})`);
fail(`Object.preventExtensions({})`);
fail(`Object.seal({})`);
fail(`Object.setPrototypeOf({}, {})`);
// Test some Object.prototype functions.
success(true, `({a:1}).hasOwnProperty("a")`);
success(true, `Object.prototype.isPrototypeOf({})`);
success(true, `({a:1}).propertyIsEnumerable("a")`);
success("[object Object]", `({a:1}).toString()`);
success("string", `(object_with_callbacks).toString()`);
success(3, `(object_with_callbacks).valueOf()`);
// Test Array functions.
success(true, `Array.isArray([1, 2, 3])`);
success([], `new Array()`);
success([undefined, undefined], `new Array(2)`);
success([1, 2], `new Array(1, 2)`);
fail(`Array.from([1, 2, 3])`);
fail(`Array.of(1, 2, 3)`);
var function_param = [
"flatMap", "forEach", "every", "some", "reduce", "reduceRight", "find",
"filter", "map", "findIndex"
];
var fails = ["toLocaleString", "pop", "push", "reverse", "shift", "unshift",
"splice", "sort", "copyWithin", "fill"];
for (f of Object.getOwnPropertyNames(Array.prototype)) {
if (typeof Array.prototype[f] === "function") {
if (fails.includes(f)) {
if (function_param.includes(f)) {
fail(`array.${f}(()=>{});`);
} else {
fail(`array.${f}();`);
}
} else if (function_param.includes(f)) {
exec_state.frame(0).evaluate(`array.${f}(()=>{});`, true);
} else {
exec_state.frame(0).evaluate(`array.${f}();`, true);
}
}
}
// Test ArrayBuffer functions.
success(3, `array_buffer.byteLength`);
success(2, `array_buffer.slice(1, 3).byteLength`);
success(true, `ArrayBuffer.isView(typed_array)`);
// Test DataView functions.
success(undefined, `new DataView(array_buffer, 1, 2)`);
success(undefined, `data_view.buffer`);
success(undefined, `data_view.byteLength`);
success(undefined, `data_view.byteOffset`);
for (f of Object.getOwnPropertyNames(DataView.prototype)) {
if (typeof data_view[f] === 'function') {
if (f.startsWith('getBig')) {
success(0n, `data_view.${f}()`);
} else if (f.startsWith('get')) {
success(0, `data_view.${f}()`);
}
}
}
// Test TypedArray functions.
success({}, `new Uint8Array()`);
success({0: 0, 1: 0}, `new Uint8Array(2)`);
success({0: 1, 1: 2, 2: 3}, `new Uint8Array(typed_array)`);
success(true, `!!typed_array.buffer`);
success(0, `typed_array.byteOffset`);
success(3, `typed_array.byteLength`);
fail(`Uint8Array.of(1, 2)`);
function_param = [
"forEach", "every", "some", "reduce", "reduceRight", "find", "filter",
"map", "findIndex"
];
fails = ["toString", "join", "toLocaleString", "reverse", "sort",
"copyWithin", "fill", "set"];
var typed_proto_proto = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array()));
for (f of Object.getOwnPropertyNames(typed_proto_proto)) {
if (typeof typed_array[f] === "function" && f !== "constructor") {
if (fails.includes(f)) {
if (function_param.includes(f)) {
fail(`typed_array.${f}(()=>{});`);
} else {
fail(`typed_array.${f}();`);
}
} else if (function_param.includes(f)) {
exec_state.frame(0).evaluate(`typed_array.${f}(()=>{});`, true);
} else {
exec_state.frame(0).evaluate(`typed_array.${f}();`, true);
}
}
}
// Test Math functions.
for (f of Object.getOwnPropertyNames(Math)) {
if (typeof Math[f] === "function") {
var result = exec_state.frame(0).evaluate(
`Math.${f}(0.5, -0.5);`, true).value();
if (f != "random") assertEquals(Math[f](0.5, -0.5), result);
}
}
// Test Number functions.
success(new Number(0), `new Number()`);
for (f of Object.getOwnPropertyNames(Number)) {
if (typeof Number[f] === "function") {
success(Number[f](0.5), `Number.${f}(0.5);`);
}
}
for (f of Object.getOwnPropertyNames(Number.prototype)) {
if (typeof Number.prototype[f] === "function") {
if (f == "toLocaleString") continue;
success(Number(0.5)[f](5), `Number(0.5).${f}(5);`);
}
}
// Test String functions.
success(new String(), `new String()`);
success(" ", "String.fromCodePoint(0x20)");
success(" ", "String.fromCharCode(0x20)");
for (f of Object.getOwnPropertyNames(String.prototype)) {
if (typeof String.prototype[f] === "function") {
// Do not expect locale-specific or regexp-related functions to work.
// {Lower,Upper}Case (Locale-specific or not) do not work either
// if Intl is enabled.
if (f.indexOf("locale") >= 0) continue;
if (f.indexOf("Locale") >= 0) continue;
if (typeof Intl !== 'undefined') {
if (f == "toUpperCase") continue;
if (f == "toLowerCase") continue;
}
if (f == "normalize") continue;
if (f == "match") continue;
if (f == "search") continue;
if (f == "split" || f == "replace") {
fail(`'abcd'.${f}(2)`);
continue;
}
success("abcd"[f](2), `"abcd".${f}(2);`);
}
}
fail("'abCd'.toLocaleLowerCase()");
fail("'abcd'.toLocaleUpperCase()");
if (typeof Intl !== 'undefined') {
fail("'abCd'.toLowerCase()");
fail("'abcd'.toUpperCase()");
}
fail("'abcd'.match(/a/)");
fail("'abcd'.replace(/a/)");
fail("'abcd'.search(/a/)");
// Test RegExp functions.
fail(`/a/.compile()`);
success('a', `/a/.exec('abc')[0]`);
success(true, `/a/.test('abc')`);
fail(`/a/.toString()`);
// Test JSON functions.
success('{"abc":[1,2]}', "JSON.stringify(JSON.parse('{\"abc\":[1,2]}'))");
// Test Symbol functions.
success(undefined, `Symbol("a")`);
fail(`Symbol.for("a")`); // Symbol.for can be observed via Symbol.keyFor.
success("a", `Symbol.keyFor(symbol_for_a)`);
success("Symbol(a)", `symbol_for_a.valueOf().toString()`);
success("Symbol(a)", `symbol_for_a[Symbol.toPrimitive]().toString()`);
} catch (e) {
exception = e;
print(e, e.stack);
};
};
// Add the debug event listener.
Debug.setListener(listener);
function f() {
debugger;
};
f();
assertNull(exception);