diff --git a/implementation-contributed/v8/intl/intl.status b/implementation-contributed/v8/intl/intl.status index 799c627c1b..d70056f049 100644 --- a/implementation-contributed/v8/intl/intl.status +++ b/implementation-contributed/v8/intl/intl.status @@ -29,36 +29,6 @@ [ALWAYS, { # TODO(jochen): The following test is flaky. 'overrides/caching': [PASS, FAIL], - - # https://bugs.chromium.org/p/v8/issues/detail?id=6891 - 'segmenter/segment': [FAIL], - 'segmenter/segment-grapheme': [FAIL], - 'segmenter/segment-grapheme-following': [FAIL], - 'segmenter/segment-grapheme-iterable': [FAIL], - 'segmenter/segment-grapheme-next': [FAIL], - 'segmenter/segment-grapheme-preceding': [FAIL], - 'segmenter/segment-iterator': [FAIL], - 'segmenter/segment-iterator-breakType': [FAIL], - 'segmenter/segment-iterator-following': [FAIL], - 'segmenter/segment-iterator-next': [FAIL], - 'segmenter/segment-iterator-position': [FAIL], - 'segmenter/segment-iterator-preceding': [FAIL], - 'segmenter/segment-line': [FAIL], - 'segmenter/segment-line-following': [FAIL], - 'segmenter/segment-line-following-modes': [FAIL], - 'segmenter/segment-line-iterable': [FAIL], - 'segmenter/segment-line-next': [FAIL], - 'segmenter/segment-line-preceding': [FAIL], - 'segmenter/segment-sentence': [FAIL], - 'segmenter/segment-sentence-following': [FAIL], - 'segmenter/segment-sentence-iterable': [FAIL], - 'segmenter/segment-sentence-next': [FAIL], - 'segmenter/segment-sentence-preceding': [FAIL], - 'segmenter/segment-word': [FAIL], - 'segmenter/segment-word-following': [FAIL], - 'segmenter/segment-word-iterable': [FAIL], - 'segmenter/segment-word-next': [FAIL], - 'segmenter/segment-word-preceding': [FAIL], }], # ALWAYS ['variant == no_wasm_traps', { diff --git a/implementation-contributed/v8/intl/segmenter/segment-iterator-following.js b/implementation-contributed/v8/intl/segmenter/segment-iterator-following.js index a28d6c31d1..c92cbaac35 100644 --- a/implementation-contributed/v8/intl/segmenter/segment-iterator-following.js +++ b/implementation-contributed/v8/intl/segmenter/segment-iterator-following.js @@ -10,6 +10,11 @@ const iter = segmenter.segment(text); assertEquals("function", typeof iter.following); +assertThrows(() => iter.following("ABC"), RangeError); +assertThrows(() => iter.following(null), RangeError); +assertThrows(() => iter.following(1.4), RangeError); +assertThrows(() => iter.following(-3), RangeError); + // 1.5.3.2 %SegmentIteratorPrototype%.following( [ from ] ) // 3.b If from >= iterator.[[SegmentIteratorString]], throw a RangeError exception. assertDoesNotThrow(() => iter.following(text.length - 1)); diff --git a/implementation-contributed/v8/intl/segmenter/segment-iterator-ownPropertyDescriptor.js b/implementation-contributed/v8/intl/segmenter/segment-iterator-ownPropertyDescriptor.js new file mode 100644 index 0000000000..e9630060a4 --- /dev/null +++ b/implementation-contributed/v8/intl/segmenter/segment-iterator-ownPropertyDescriptor.js @@ -0,0 +1,38 @@ +// Copyright 2018 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: --harmony-intl-segmenter + +let seg = new Intl.Segmenter(); +let descriptor = Object.getOwnPropertyDescriptor( + Intl.Segmenter, "supportedLocalesOf"); +assertTrue(descriptor.writable); +assertFalse(descriptor.enumerable); +assertTrue(descriptor.configurable); + +// ecma402 #sec-Intl.Segmenter.prototype +// Intl.Segmenter.prototype +// The value of Intl.Segmenter.prototype is %SegmenterPrototype%. +// This property has the attributes +// { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. +descriptor = Object.getOwnPropertyDescriptor(Intl.Segmenter, "prototype"); +assertFalse(descriptor.writable); +assertFalse(descriptor.enumerable); +assertFalse(descriptor.configurable); + +for (let func of ["segment", "resolvedOptions"]) { + let descriptor = Object.getOwnPropertyDescriptor( + Intl.Segmenter.prototype, func); + assertTrue(descriptor.writable); + assertFalse(descriptor.enumerable); + assertTrue(descriptor.configurable); +} + +let prototype = Object.getPrototypeOf(seg.segment('text')); +for (let func of ["next", "following", "preceding"]) { + let descriptor = Object.getOwnPropertyDescriptor(prototype, func); + assertTrue(descriptor.writable); + assertFalse(descriptor.enumerable); + assertTrue(descriptor.configurable); +} diff --git a/implementation-contributed/v8/intl/segmenter/segment-iterator-preceding.js b/implementation-contributed/v8/intl/segmenter/segment-iterator-preceding.js index 07d73376f2..0130a4d229 100644 --- a/implementation-contributed/v8/intl/segmenter/segment-iterator-preceding.js +++ b/implementation-contributed/v8/intl/segmenter/segment-iterator-preceding.js @@ -10,6 +10,11 @@ const iter = segmenter.segment(text); assertEquals("function", typeof iter.preceding); +assertThrows(() => iter.preceding("ABC"), RangeError); +assertThrows(() => iter.preceding(null), RangeError); +assertThrows(() => iter.preceding(1.4), RangeError); +assertThrows(() => iter.preceding(-3), RangeError); + // 1.5.3.3 %SegmentIteratorPrototype%.preceding( [ from ] ) // 3.b If ... from = 0, throw a RangeError exception. assertThrows(() => iter.preceding(0), RangeError); diff --git a/implementation-contributed/v8/intl/segmenter/segment-iterator.js b/implementation-contributed/v8/intl/segmenter/segment-iterator.js index 45cb67ab5a..2821c8faaa 100644 --- a/implementation-contributed/v8/intl/segmenter/segment-iterator.js +++ b/implementation-contributed/v8/intl/segmenter/segment-iterator.js @@ -4,7 +4,6 @@ // Flags: --harmony-intl-segmenter -let descriptor; const text = "Hello World, Test 123! Foo Bar. How are you?"; for (const granularity of ["grapheme", "word", "sentence", "line"]) { const segmenter = new Intl.Segmenter("en", { granularity }); diff --git a/implementation-contributed/v8/intl/segmenter/segment.js b/implementation-contributed/v8/intl/segmenter/segment.js index ca17c5040d..4c76b96e54 100644 --- a/implementation-contributed/v8/intl/segmenter/segment.js +++ b/implementation-contributed/v8/intl/segmenter/segment.js @@ -5,3 +5,35 @@ // Flags: --harmony-intl-segmenter assertEquals("function", typeof Intl.Segmenter.prototype.segment); +assertEquals(1, Intl.Segmenter.prototype.segment.length); + +let seg = new Intl.Segmenter("en", {granularity: "word"}) +let res; + +// test with 0 args +assertDoesNotThrow(() => res = seg.segment()) +// test with 1 arg +assertDoesNotThrow(() => res = seg.segment("hello")) +assertEquals("hello", res.next().value.segment); +// test with 2 args +assertDoesNotThrow(() => res = seg.segment("hello world")) +assertEquals("hello", res.next().value.segment); + +// test with other types +assertDoesNotThrow(() => res = seg.segment(undefined)) +assertEquals("undefined", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(null)) +assertEquals("null", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(true)) +assertEquals("true", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(false)) +assertEquals("false", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(1234)) +assertEquals("1234", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(3.1415926)) +assertEquals("3.1415926", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment(["hello","world"])) +assertEquals("hello", res.next().value.segment); +assertDoesNotThrow(() => res = seg.segment({k: 'v'})) +assertEquals("[", res.next().value.segment); +assertThrows(() => res = seg.segment(Symbol()), TypeError) diff --git a/implementation-contributed/v8/mjsunit/array-join-index-getter-side-effects.js b/implementation-contributed/v8/mjsunit/array-join-index-getter-side-effects.js index 12fe5786c7..4b843464df 100644 --- a/implementation-contributed/v8/mjsunit/array-join-index-getter-side-effects.js +++ b/implementation-contributed/v8/mjsunit/array-join-index-getter-side-effects.js @@ -48,6 +48,25 @@ // Verifies cycle detection still works properly after continuation. assertSame('9,2', a.join()); + assertSame(2, callCount); +})(); + +(function ArrayLengthIncreasedWithHole() { + let callCount = 0; + const a = [1, , 2]; + Object.defineProperty(a, '1', { + configurable: true, + get() { + callCount++; + a.push(3); + } + }); + assertSame('1,,2', a.join()); + assertSame(1, callCount); + + // Verifies cycle detection still works properly after continuation. + assertSame('1,,2,3', a.join()); + assertSame(2, callCount); })(); (function ArrayLengthDecreased() { @@ -66,6 +85,7 @@ // Verifies cycle detection still works properly after continuation. assertSame('9', a.join()); + assertSame(2, callCount); })(); (function ElementsKindChangedToHoley() { @@ -84,4 +104,5 @@ // Verifies cycle detection still works properly after continuation. assertSame('9,1,', a.join()); + assertSame(2, callCount); })(); diff --git a/implementation-contributed/v8/mjsunit/compiler/promise-resolve-stable-maps.js b/implementation-contributed/v8/mjsunit/compiler/promise-resolve-stable-maps.js new file mode 100644 index 0000000000..7acd891b9b --- /dev/null +++ b/implementation-contributed/v8/mjsunit/compiler/promise-resolve-stable-maps.js @@ -0,0 +1,61 @@ +// Copyright 2018 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: --allow-natives-syntax --opt --noalways-opt + +// Test that JSResolvePromise takes a proper stability dependency +// on the resolutions map if the infer receiver maps are unreliable +// (as is the case for HeapConstants). +(function() { + // We need an object literal which gets a stable map initially. + function makeObjectWithStableMap() { + return {a:1, b:1, c:1}; + } + const a = makeObjectWithStableMap(); + + function foo() { + return Promise.resolve(a); + } + + assertInstanceof(foo(), Promise); + assertInstanceof(foo(), Promise); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), Promise); + assertOptimized(foo); + + // Now invalidate the stability of a's map. + const b = makeObjectWithStableMap(); + b.d = 1; + + // This should deoptimize foo. + assertUnoptimized(foo); +})(); + +// Same test with async functions. +(function() { + // We need an object literal which gets a stable map initially, + // it needs to be different from the above, otherwise the map + // is already not stable when we get here. + function makeObjectWithStableMap() { + return {x:1, y:1}; + } + const a = makeObjectWithStableMap(); + + async function foo() { + return a; + } + + assertInstanceof(foo(), Promise); + assertInstanceof(foo(), Promise); + %OptimizeFunctionOnNextCall(foo); + assertInstanceof(foo(), Promise); + assertOptimized(foo); + + // Now invalidate the stability of a's map. + const b = makeObjectWithStableMap(); + b.z = 1; + + // This should deoptimize foo. + assertUnoptimized(foo); +})(); diff --git a/implementation-contributed/v8/mjsunit/es6/regress/regress-cr895860.js b/implementation-contributed/v8/mjsunit/es6/regress/regress-cr895860.js new file mode 100644 index 0000000000..1ecd1f7730 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/es6/regress/regress-cr895860.js @@ -0,0 +1,14 @@ +// Copyright 2018 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. + +(function() { + var s = "f"; + + // 2^18 length, enough to ensure an array (of pointers) bigger than 500KB. + for (var i = 0; i < 18; i++) { + s += s; + } + + var ss = [...s]; +})(); diff --git a/implementation-contributed/v8/mjsunit/harmony/weakrefs/cleanup-doesnt-iterate-all-cells.js b/implementation-contributed/v8/mjsunit/harmony/weakrefs/cleanup-doesnt-iterate-all-cells.js new file mode 100644 index 0000000000..08e4619a20 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/harmony/weakrefs/cleanup-doesnt-iterate-all-cells.js @@ -0,0 +1,89 @@ +// Copyright 2018 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: --harmony-weak-refs --expose-gc + +let cleanup_call_count = 0; +let cleanup = function(iter) { + if (cleanup_call_count == 0) { + // First call: iterate 2 of the 3 cells + let cells = []; + for (wc of iter) { + cells.push(wc); + // Don't iterate the rest of the cells + if (cells.length == 2) { + break; + } + } + assertEquals(cells.length, 2); + assertTrue(cells[0].holdings < 3); + assertTrue(cells[1].holdings < 3); + // Update call count only after the asserts; this ensures that the test + // fails even if the exceptions inside the cleanup function are swallowed. + cleanup_call_count++; + } else { + // Second call: iterate one leftover cell and one new cell. + assertEquals(1, cleanup_call_count); + let cells = []; + for (wc of iter) { + cells.push(wc); + } + assertEquals(cells.length, 2); + assertTrue((cells[0].holdings < 3 && cells[1].holdings == 100) || + (cells[1].holdings < 3 && cells[0].holdings == 100)); + // Update call count only after the asserts; this ensures that the test + // fails even if the exceptions inside the cleanup function are swallowed. + cleanup_call_count++; + } +} + +let wf = new WeakFactory(cleanup); +// Create 3 objects and WeakCells pointing to them. The objects need to be +// inside a closure so that we can reliably kill them! +let weak_cells = []; + +(function() { + let objects = []; + + for (let i = 0; i < 3; ++i) { + objects[i] = {a: i}; + weak_cells[i] = wf.makeCell(objects[i], i); + } + + gc(); + assertEquals(0, cleanup_call_count); + + // Drop the references to the objects. + objects = []; +})(); + +// This GC will discover dirty WeakCells. +gc(); +assertEquals(0, cleanup_call_count); + +let timeout_func_1 = function() { + assertEquals(1, cleanup_call_count); + + // Assert that the cleanup function won't be called unless new WeakCells appear. + setTimeout(timeout_func_2, 0); +} + +setTimeout(timeout_func_1, 0); + +let timeout_func_2 = function() { + assertEquals(1, cleanup_call_count); + + // Create a new WeakCells to be cleaned up. + let obj = {}; + let wc = wf.makeCell(obj, 100); + obj = null; + + gc(); + + setTimeout(timeout_func_3, 0); +} + +let timeout_func_3 = function() { + assertEquals(2, cleanup_call_count); +} diff --git a/implementation-contributed/v8/mjsunit/harmony/weakrefs/factory-scheduled-for-cleanup-multiple-times.js b/implementation-contributed/v8/mjsunit/harmony/weakrefs/factory-scheduled-for-cleanup-multiple-times.js new file mode 100644 index 0000000000..7dcf823b92 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/harmony/weakrefs/factory-scheduled-for-cleanup-multiple-times.js @@ -0,0 +1,70 @@ +// Copyright 2018 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: --harmony-weak-refs --expose-gc + +let cleanup0_call_count = 0; +let cleanup0_weak_cell_count = 0; + +let cleanup1_call_count = 0; +let cleanup1_weak_cell_count = 0; + +let cleanup0 = function(iter) { + for (wc of iter) { + ++cleanup0_weak_cell_count; + } + ++cleanup0_call_count; +} + +let cleanup1 = function(iter) { + for (wc of iter) { + ++cleanup1_weak_cell_count; + } + ++cleanup1_call_count; +} + +let wf0 = new WeakFactory(cleanup0); +let wf1 = new WeakFactory(cleanup1); + +// Create 1 WeakCell for each WeakFactory and kill the objects they point to. +(function() { + // The objects need to be inside a closure so that we can reliably kill them. + let objects = []; + objects[0] = {}; + objects[1] = {}; + + wf0.makeCell(objects[0]); + wf1.makeCell(objects[1]); + + // Drop the references to the objects. + objects = []; + + // Will schedule both wf0 and wf1 for cleanup. + gc(); +})(); + +// Before the cleanup task has a chance to run, do the same thing again, so both +// factories are (again) scheduled for cleanup. This has to be a IIFE function +// (so that we can reliably kill the objects) so we cannot use the same function +// as before. +(function() { + let objects = []; + objects[0] = {}; + objects[1] = {}; + wf0.makeCell(objects[0]); + wf1.makeCell(objects[1]); + objects = []; + gc(); +})(); + +let timeout_func = function() { + assertEquals(1, cleanup0_call_count); + assertEquals(2, cleanup0_weak_cell_count); + assertEquals(1, cleanup1_call_count); + assertEquals(2, cleanup1_weak_cell_count); +} + +// Give the cleanup task a chance to run. All WeakCells to cleanup will be +// available during the same invocation of the cleanup function. +setTimeout(timeout_func, 0); diff --git a/implementation-contributed/v8/mjsunit/harmony/weakrefs/weak-factory-keeps-weak-cells-alive.js b/implementation-contributed/v8/mjsunit/harmony/weakrefs/weak-factory-keeps-weak-cells-alive.js new file mode 100644 index 0000000000..93a040aeae --- /dev/null +++ b/implementation-contributed/v8/mjsunit/harmony/weakrefs/weak-factory-keeps-weak-cells-alive.js @@ -0,0 +1,39 @@ +// Copyright 2018 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: --harmony-weak-refs --expose-gc + +let cleanup_called = false; +let cleanup = function(iter) { + assertFalse(cleanup_called); + let cells = []; + for (wc of iter) { + cells.push(wc); + } + assertEquals(cells.length, 1); + assertEquals(cells[0].holdings, "this is my cell"); + cleanup_called = true; +} + +let wf = new WeakFactory(cleanup); +let o1 = {}; +let wc1 = wf.makeCell(o1, "this is my cell"); + +gc(); +assertFalse(cleanup_called); + +// Drop the last references to o1. +o1 = null; + +// Drop the last reference to the WeakCell. The WeakFactory keeps it alive, so +// the cleanup function will be called as normal. +wc1 = null; +gc(); +assertFalse(cleanup_called); + +let timeout_func = function() { + assertTrue(cleanup_called); +} + +setTimeout(timeout_func, 0); diff --git a/implementation-contributed/v8/mjsunit/mjsunit.status b/implementation-contributed/v8/mjsunit/mjsunit.status index 3d72dd63a9..d87b4b907f 100644 --- a/implementation-contributed/v8/mjsunit/mjsunit.status +++ b/implementation-contributed/v8/mjsunit/mjsunit.status @@ -901,44 +901,4 @@ 'wasm/asm-wasm-f64': [SKIP], }], # arch == x64 -############################################################################## -['arch == ia32 and embedded_builtins == True', { - # TODO(v8:6666): Fix arguments adaptor trampoline - 'wasm/compiled-module-serialization': [SKIP], - 'asm/embenchen/copy': [SKIP], - 'wasm/embenchen/corrections': [SKIP], - 'asm/embenchen/primes': [SKIP], - 'asm/embenchen/corrections': [SKIP], - 'wasm/embenchen/copy': [SKIP], - 'asm/embenchen/fannkuch': [SKIP], - 'asm/embenchen/memops': [SKIP], - 'asm/embenchen/fasta': [SKIP], - 'wasm/embenchen/fannkuch': [SKIP], - 'asm/embenchen/zlib': [SKIP], - 'wasm/embenchen/fasta': [SKIP], - 'wasm/embenchen/primes': [SKIP], - 'wasm/embenchen/box2d': [SKIP], - 'asm/embenchen/box2d': [SKIP], - 'wasm/embenchen/memops': [SKIP], - 'wasm/embenchen/zlib': [SKIP], - 'asm/embenchen/lua_binarytrees': [SKIP], - 'wasm/embenchen/lua_binarytrees': [SKIP], - 'asm/sqlite3/sqlite': [SKIP], - 'asm/sqlite3/sqlite-safe-heap': [SKIP], - 'asm/sqlite3/sqlite-pointer-masking': [SKIP], - 'asm/poppler/poppler': [SKIP], - 'regress/wasm/regress-808848': [SKIP], - 'regress/wasm/regress-834624': [SKIP], - 'regress/wasm/regress-843563': [SKIP], - 'wasm/anyref': [SKIP], - 'wasm/exceptions-shared': [SKIP], - 'wasm/errors': [SKIP], - 'wasm/ffi-error': [SKIP], - 'wasm/gc-frame': [SKIP], - 'wasm/import-function': [SKIP], - 'wasm/ffi': [SKIP], - 'wasm/test-wasm-module-builder': [SKIP], - 'wasm/stackwalk': [SKIP], -}], # arch == ia32 and embedded_builtins == True - ] diff --git a/implementation-contributed/v8/mjsunit/regress/regress-crbug-896181.js b/implementation-contributed/v8/mjsunit/regress/regress-crbug-896181.js new file mode 100644 index 0000000000..9aef4fc1d5 --- /dev/null +++ b/implementation-contributed/v8/mjsunit/regress/regress-crbug-896181.js @@ -0,0 +1,14 @@ +// Copyright 2018 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. + +var a = new Array(); +a[0] = 0.1; +a[2] = 0.2; +Object.defineProperty(a, 1, { + get: function() { + a[4] = 0.3; + }, +}); + +assertSame('0.1,,0.2', a.join());