Commit 6e821a78 authored by Findit's avatar Findit

Revert "Align resource timing buffer full processing to spec PR 168"

This reverts commit 579d6501.

Reason for revert:

Findit (https://goo.gl/kROfz5) identified CL at revision 610667 as the
culprit for flakes in the build cycles as shown on:
https://findit-for-me.appspot.com/waterfall/flake/flake-culprit?key=ag9zfmZpbmRpdC1mb3ItbWVyQwsSDEZsYWtlQ3VscHJpdCIxY2hyb21pdW0vNTc5ZDY1MDE0YzlkNmNjMjQ4ZWMxZGU0NzAxM2JmNmMyMGM3MjE1OAw

Sample Failed Build: https://ci.chromium.org/buildbot/chromium.webkit/WebKit%20Linux%20Trusty%20Leak/26746

Sample Failed Step: webkit_layout_tests

Sample Flaky Test: external/wpt/resource-timing/buffer-full-store-and-clear-during-callback.html

Original change's description:
> Align resource timing buffer full processing to spec PR 168
> 
> This change implements the processing model from PR 168[1], when
> it comes to setResourceTimingBufferSize(), clearResourceTimings()
> and the firing of the resourcetimingbufferfull event.
> 
> [1] https://github.com/w3c/resource-timing/pull/168
> 
> Change-Id: I3a57196f10e0b4cf2bae5662b0e075673a0c2d80
> Reviewed-on: https://chromium-review.googlesource.com/c/1345269
> Commit-Queue: Yoav Weiss <yoavweiss@chromium.org>
> Commit-Queue: Yoav Weiss <yoav@yoav.ws>
> Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#610667}

Change-Id: I0840bd9b763030b6e200e8f9a94c73c7982044a0
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 908181
Reviewed-on: https://chromium-review.googlesource.com/c/1349498
Cr-Commit-Position: refs/heads/master@{#610683}
parent 8bc2e0de
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="help" href="https://w3c.github.io/resource-timing/#dom-performance-setresourcetimingbuffersize">
<title>This test validates that setResourceTimingBufferFull behaves appropriately when set to the current buffer level.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
let eventFired = false;
function loadRandomResource() {
return fetch(window.location.href + "?" + Math.random());
}
setup(function() {
// Get the browser into a consistent state.
performance.clearResourceTimings();
performance.setResourceTimingBufferSize(3);
});
let gatherEntries = new Promise(function(resolve, reject) {
// Gather up 3 Resource Entries to kick off the rest of test behavior.
let resources = 0;
let observer = new PerformanceObserver(function(list) {
resources += list.getEntriesByType("resource").length;
if (resources !== 3)
return;
observer.disconnect();
resolve();
});
observer.observe({entryTypes: ["resource"]});
for (let i = 0; i < 3; ++i)
loadRandomResource();
});
let setBufferSize = new Promise(function(resolve, reject) {
performance.onresourcetimingbufferfull = function() {
eventFired = true;
performance.clearResourceTimings();
};
resolve();
});
promise_test(function() {
return gatherEntries;
}, "Reset the entries number");
promise_test(function() {
return setBufferSize;
}, "Set the buffer size");
promise_test(function() {
return new Promise(function(resolve, reject) {
loadRandomResource().then(resolve);
});
}, "Overflow the buffer");
/*
promise_test(function() {
return new Promise(function(resolve, reject) {
let waitForIt = function() {
if (eventFired) {
eventFired = false;
resolve();
}
}
step_timeout(waitForIt, 0);
});
}, "Wait for event");
*/
promise_test(function() {
return new Promise(function(resolve, reject) {
performance.clearResourceTimings();
loadRandomResource().then(function() {
resolve();
})});
}, "Clear and add another entry to the buffer");
promise_test(function() {
return new Promise(function(resolve, reject) {
let waitForIt = function() {
if (performance.getEntriesByType("resource").length) {
resolve();
} else {
reject("After buffer full, entry never added to primary");
}
}
step_timeout(waitForIt, 0);
});
}, "Wait for entry to be added");
</script>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
promise_test(()=>{
return new Promise((resolve, reject)=>{
const resource_timing_buffer_size = 1;
performance.clearResourceTimings();
var add_entry = function() {
performance.setResourceTimingBufferSize(resource_timing_buffer_size + 1);
// The sync attribute is added to the secondary buffer, so will be last one there and eventually dropped.
xhrScript("resources/empty.js?xhr");
resolve();
}
performance.addEventListener('resourcetimingbufferfull', add_entry);
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
appendScript('resources/empty.js');
// This resource overflows the entry buffer, and goes into the secondary buffer.
appendScript('resources/empty_script.js');
});
}, "Prepare test");
promise_test(function() {
return new Promise(function(resolve, reject) {
let waitForIt = function() {
resolve();
}
step_timeout(waitForIt, 0);
});
}, "Wait for next task");
promise_test(()=>{
return new Promise((resolve, reject)=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 2,
'Both entries should be stored in resource timing buffer since its increases size once it overflows.');
assert_true(entries[0].name.includes('empty.js'), "empty.js is in the entries buffer");
assert_true(entries[1].name.includes('empty_script.js'), "empty_script.js is in the entries buffer");
resolve();
});
}, "Test");
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const resource_timing_buffer_size = 1;
const t = async_test("Verify that adding entries to the resource timing buffer during resourcetimingbufferfull call works");
performance.clearResourceTimings();
var add_entry = function() {
performance.setResourceTimingBufferSize(resource_timing_buffer_size + 2);
xhrScript("resources/empty.js?xhr");
}
performance.addEventListener('resourcetimingbufferfull', add_entry);
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
appendScript('resources/empty.js');
// This resource overflows the entry buffer, and goes into the secondary buffer.
appendScript('resources/empty_script.js');
window.onload = t.step_func_done(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 3,
'All entries should be stored in resource timing buffer since its increases size once it overflows.');
assert_true(entries[0].name.includes('empty.js'), "empty.js is in the entries buffer");
assert_true(entries[1].name.includes('empty_script.js'), "empty_script.js is in the entries buffer");
assert_true(entries[2].name.includes('empty.js?xhr'), "empty.js?xhr is in the entries buffer");
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const resource_timing_buffer_size = 1;
const t = async_test("Verify that adding entries and then clearing the resource timing buffer results in entries added in the right order");
performance.clearResourceTimings();
performance.addEventListener('resourcetimingbufferfull', t.unreached_func("resourcetimingbufferfull should not fire"));
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
xhrScript('resources/empty.js?xhr');
// These resources overflow the entry buffer, and goes into the secondary buffer.
xhrScript('resources/empty.js?xhr2');
xhrScript('resources/empty.js?xhr3');
performance.clearResourceTimings();
performance.setResourceTimingBufferSize(3);
xhrScript('resources/empty.js?xhr4');
let entriesAfterAddition = performance.getEntriesByType('resource');
window.onload = t.step_timeout(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 3,
'the last 3 resources should be in the buffer, since the first one was cleared');
assert_true(entries[0].name.includes('empty.js?xhr2'), "empty.js?xhr2 is in the entries buffer");
assert_true(entries[1].name.includes('empty.js?xhr3'), "empty.js?xhr3 is in the entries buffer");
assert_true(entries[2].name.includes('empty.js?xhr4'), "empty.js?xhr4 is in the entries buffer");
assert_equals(entriesAfterAddition.length, 0, "No entries should have been added to the primary buffer before the task to 'fire a buffer full event'.");
t.done();
}, 0);
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates that decreasing the buffer size in onresourcetimingbufferfull callback does not result in extra entries being dropped.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const resource_timing_buffer_size = 2;
const t = async_test("Verify that reducing the size of the resource timing buffer during resourcetimingbufferfull call works");
performance.clearResourceTimings();
let resize = function() {
performance.setResourceTimingBufferSize(resource_timing_buffer_size - 1);
}
performance.addEventListener('resourcetimingbufferfull', resize);
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
xhrScript('resources/empty.js');
xhrScript('resources/empty.js?second');
// This resource overflows the entry buffer, and goes into the secondary buffer.
xhrScript('resources/empty_script.js');
window.onload = t.step_func_done(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 2,
'Both entries should be stored in resource timing buffer since it decreased its limit only after it overflowed.');
assert_true(entries[0].name.includes('empty.js'), "empty.js is in the entries buffer");
assert_true(entries[1].name.includes('empty.js?second'), "empty.js?second is in the entries buffer");
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates increasing the buffer size in onresourcetimingbufferfull callback of resource timing.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const resource_timing_buffer_size = 1;
const t = async_test("Verify that increasing the resource timing buffer during resourcetimingbufferfull call works");
performance.clearResourceTimings();
var increase = function() {
performance.setResourceTimingBufferSize(resource_timing_buffer_size * 2);
}
performance.addEventListener('resourcetimingbufferfull', increase);
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
appendScript('resources/empty.js');
// This resource overflows the entry buffer, and goes into the secondary buffer.
appendScript('resources/empty_script.js');
window.onload = t.step_func_done(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 2,
'Both entries should be stored in resource timing buffer since its increases size once it overflows.');
assert_true(entries[0].name.includes('empty.js'), "empty.js is in the entries buffer");
assert_true(entries[1].name.includes('empty_script.js'), "empty_script.js is in the entries buffer");
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates the buffer doesn't contain more entries than it should inside onresourcetimingbufferfull callback.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const t = async_test("Verify that inspecting the resource timing buffer during resourcetimingbufferfull call doesn't exceed the limit.");
let resource_timing_buffer_size = 2;
performance.clearResourceTimings();
var resize = function() {
assert_equals(performance.getEntriesByType("resource").length, resource_timing_buffer_size, "resource timing buffer in resourcetimingbufferfull is the size of the limit");
++resource_timing_buffer_size;
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
xhrScript("resources/empty.js?xhr");
assert_equals(performance.getEntriesByType("resource").length, resource_timing_buffer_size - 1, "A sync request was not added to the primary buffer just yet, because it is full");
++resource_timing_buffer_size;
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
}
performance.addEventListener('resourcetimingbufferfull', t.step_func(resize));
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// These resources gets buffered in the resource timing entry buffer.
appendScript('resources/empty.js');
appendScript('resources/empty.js?second');
// This resource overflows the entry buffer, and goes into the secondary buffer.
appendScript('resources/empty_script.js');
window.onload = t.step_func_done(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, resource_timing_buffer_size,
'All 4 entries should be stored in resource timing buffer.');
assert_true(entries[0].name.includes('empty.js'), "empty.js is in the entries buffer");
assert_true(entries[1].name.includes('empty.js?second'), "empty.js?second is in the entries buffer");
assert_true(entries[2].name.includes('empty_script.js'), "empty_script.js is in the entries buffer");
assert_true(entries[3].name.includes('empty.js?xhr'), "empty.js?xhr is in the entries buffer");
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="help" href="https://w3c.github.io/resource-timing/#dom-performance-setresourcetimingbuffersize">
<title>This test validates that setResourceTimingBufferFull behaves appropriately when set to the current buffer level.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
let eventFired = false;
function loadRandomResource() {
return fetch(window.location.href + "?" + Math.random());
}
setup(function() {
// Get the browser into a consistent state.
performance.clearResourceTimings();
performance.setResourceTimingBufferSize(100);
window.result = "";
});
let gatherEntries = new Promise(function(resolve, reject) {
// Gather up 3 Resource Entries to kick off the rest of test behavior.
let resources = 0;
let observer = new PerformanceObserver(function(list) {
resources += list.getEntriesByType("resource").length;
if (resources !== 3)
return;
observer.disconnect();
resolve();
});
observer.observe({entryTypes: ["resource"]});
for (let i = 0; i < 3; ++i)
loadRandomResource();
});
let setBufferSize = new Promise(function(resolve, reject) {
performance.onresourcetimingbufferfull = function() {
eventFired = true;
window.result += "Event Fired with " + performance.getEntriesByType("resource").length + " entries. ";
performance.clearResourceTimings();
};
window.result += "before setLimit(3). ";
performance.setResourceTimingBufferSize(3);
window.result += "after setLimit(3). ";
resolve();
});
promise_test(function() {
return gatherEntries;
}, "Reset the entries number");
promise_test(function() {
return setBufferSize;
}, "Set the buffer size");
promise_test(function() {
return new Promise(function(resolve, reject) {
loadRandomResource().then(function() {
window.result += "after loading 4th resource. ";
resolve();
})});
}, "Overflow the buffer");
promise_test(function() {
return new Promise(function(resolve, reject) {
let waitForIt = function() {
if (eventFired) {
resolve();
}
}
step_timeout(waitForIt, 0);
});
}, "Wait for event");
promise_test(function() {
return new Promise(function(resolve, reject) {
if (window.result != "before setLimit(3). after setLimit(3). after loading 4th resource. Event Fired with 3 entries. ") {
reject("Non matching value: " + window.result);
}
let entries = performance.getEntriesByType("resource");
if (entries.length != 1) {
reject("Number of entries in resource timing buffer is unexpected: " + entries.length);
}
resolve();
});
}, "Check result");
</script>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates the behavior of read and clear operation in onresourcetimingbufferfull callback of resource timing.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const t = async_test("Verify that clearing the resource timing buffer and storing the entries during resourcetimingbufferfull call works");
const resource_timing_buffer_size = 1;
performance.clearResourceTimings();
let global_buffer = [];
let store_and_clear = function() {
const entryList = performance.getEntriesByType('resource');
entryList.forEach(function (entry) {
global_buffer.push(entry);
});
performance.clearResourceTimings();
}
performance.addEventListener('resourcetimingbufferfull', store_and_clear);
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
appendScript('resources/empty.js');
// This resource overflows the entry buffer, and goes into the secondary buffer.
appendScript('resources/empty_script.js');
window.onload = t.step_func_done(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 1,
"Only the last entry should be stored in resource timing buffer since it's cleared once it overflows.");
assert_equals(global_buffer.length, 1, '1 resource timing entry should be moved to global buffer.');
assert_true(global_buffer[0].name.includes('empty.js'), "empty.js is in the global buffer");
assert_true(entries[0].name.includes('empty_script.js'), "empty_script.js is in the entries buffer");
});
</script>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/append.js"></script>
</head>
<body>
<script>
const resource_timing_buffer_size = 1;
const t = async_test("Verify that adding entries and then increasing the size of the resource timing buffer results in entries added in the right order");
performance.clearResourceTimings();
performance.addEventListener('resourcetimingbufferfull', t.unreached_func("resourcetimingbufferfull should not fire"));
performance.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
// This resource gets buffered in the resource timing entry buffer.
xhrScript('resources/empty.js?xhr');
// These resources overflow the entry buffer, and goes into the secondary buffer.
xhrScript('resources/empty.js?xhr2');
xhrScript('resources/empty.js?xhr3');
performance.setResourceTimingBufferSize(3);
window.onload = t.step_timeout(()=>{
let entries = performance.getEntriesByType('resource');
assert_equals(entries.length, 3,
'All resources should be in the buffer, since its size was increased');
assert_true(entries[0].name.includes('empty.js?xhr'), "empty.js?xhr2 is in the entries buffer");
assert_true(entries[1].name.includes('empty.js?xhr2'), "empty.js?xhr3 is in the entries buffer");
assert_true(entries[2].name.includes('empty.js?xhr3'), "empty.js?xhr3 is in the entries buffer");
t.done();
}, 0);
</script>
</body>
</html>
...@@ -9,29 +9,33 @@ ...@@ -9,29 +9,33 @@
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<script src="resources/webperftestharness.js"></script> <script src="resources/webperftestharness.js"></script>
<script src="resources/webperftestharnessextension.js"></script> <script src="resources/webperftestharnessextension.js"></script>
<script src="resources/append.js"></script>
</head> </head>
<body> <body onload=onload_test()>
<script> <script>
const context = new PerformanceContext(performance); const context = new PerformanceContext(performance);
const t = async_test("Verify that resourcetimingbufferfull is properly invoked"); const bufferSize = 5;
performance.clearResourceTimings();
let bufferSize = 2;
context.setResourceTimingBufferSize(bufferSize); context.setResourceTimingBufferSize(bufferSize);
let bufferFullCount = 0; let bufferFullCount = 0;
function buffer_full_callback(e) { function buffer_full_callback() {
assert_equals(e.bubbles, false, "Event bubbles attribute is false");
bufferFullCount++; bufferFullCount++;
} }
context.registerResourceTimingBufferFullCallback(t.step_func(buffer_full_callback)); context.registerResourceTimingBufferFullCallback(buffer_full_callback);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before. // Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
function appendScript(src) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.body.appendChild(script);
}
appendScript('resources/empty.js'); appendScript('resources/empty.js');
appendScript('resources/empty_script.js'); appendScript('resources/empty_script.js');
appendScript('resources/resource_timing_test0.js'); appendScript('resources/resource_timing_test0.js');
window.onload = t.step_func_done(()=>{ setup({ explicit_done: true });
assert_equals(context.getEntriesByType('resource').length, bufferSize, 'There should only be |bufferSize| resource entries.'); function onload_test() {
assert_equals(bufferFullCount, 1, 'onresourcetimingbufferfull should have been invoked once.'); test_equals(context.getEntriesByType('resource').length, bufferSize, 'There should only be |bufferSize| resource entries.');
}); test_equals(bufferFullCount, 1, 'onresourcetimingbufferfull should have been invoked once buffer is full.');
done();
}
</script> </script>
</body> </body>
</html> </html>
This is a testharness.js-based test.
PASS There are 4 scripts, and setResourceTimingBufferSize does not reduce the size.
FAIL onresourcetimingbufferfull should not be invoked during setResourceTimingBufferSize. assert_equals: onresourcetimingbufferfull should not be invoked during setResourceTimingBufferSize. expected 0 but got 2
Harness: the test ran to completion.
This is a testharness.js-based test.
PASS No entry should be stored in resource timing buffer since its cleared once an item arrived.
FAIL 6 resource timing entries should be moved to global buffer. assert_equals: 6 resource timing entries should be moved to global buffer. expected 6 but got 7
FAIL http://web-platform.test:8001/resource-timing/resources/empty.js is not expected to be in the Resource Timing buffer assert_unreached: Reached unreachable code
PASS http://web-platform.test:8001/resource-timing/resources/empty_script.js is expected to have initiatorType script
PASS http://web-platform.test:8001/resource-timing/resources/resource_timing_test0.js is expected to have initiatorType script
PASS http://web-platform.test:8001/resource-timing/resources/webperftestharness.js is expected to have initiatorType script
PASS http://web-platform.test:8001/resource-timing/resources/webperftestharnessextension.js is expected to have initiatorType script
PASS http://web-platform.test:8001/resources/testharness.js is expected to have initiatorType script
PASS http://web-platform.test:8001/resources/testharnessreport.js is expected to have initiatorType script
Harness: the test ran to completion.
<!DOCTYPE HTML>
<html>
<head onload>
<meta charset="utf-8" />
<title>This test validates the behavior of read and clear operation in onresourcetimingbufferfull callback of resource timing.</title>
<link rel="author" title="Intel" href="http://www.intel.com/" />
<link rel="help" href="http://www.w3.org/TR/resource-timing/#performanceresourcetiming"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/webperftestharness.js"></script>
<script src="resources/webperftestharnessextension.js"></script>
</head>
<body onload=onload_test()>
<script>
const context = new PerformanceContext(performance);
const resource_timing_buffer_size = 1;
let global_buffer = [];
function store_and_clear() {
const entryList = context.getEntriesByType('resource');
entryList.forEach(function (entry) {
global_buffer.push(entry);
});
context.clearResourceTimings();
}
context.registerResourceTimingBufferFullCallback(store_and_clear);
context.setResourceTimingBufferSize(resource_timing_buffer_size);
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
function appendScript(src) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.body.appendChild(script);
}
appendScript('resources/empty.js');
appendScript('resources/empty_script.js');
appendScript('resources/resource_timing_test0.js');
setup({ explicit_done: true });
function onload_test() {
test_equals(context.getEntriesByType('resource').length, 0, 'No entry should be stored in resource timing buffer since its cleared once an item arrived.');
// The entry for empty.js must not be in the global buffer, but all others should be.
test_equals(global_buffer.length, 6, '6 resource timing entries should be moved to global buffer.');
const index = window.location.pathname.lastIndexOf('resource-timing');
const pathname = window.location.pathname.substring(0, index);
let expected_entries = {};
expected_entries[pathname + 'resources/testharness.js'] = 'script';
expected_entries[pathname + 'resources/testharnessreport.js'] = 'script';
expected_entries[pathname + 'resource-timing/resources/webperftestharness.js'] = 'script';
expected_entries[pathname + 'resource-timing/resources/webperftestharnessextension.js'] = 'script';
expected_entries[pathname + 'resource-timing/resources/empty_script.js'] = 'script';
expected_entries[pathname + 'resource-timing/resources/resource_timing_test0.js'] = 'script';
test_resource_entries(global_buffer, expected_entries);
done();
}
</script>
</body>
</html>
function appendScript(src) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.body.appendChild(script);
}
function xhrScript(src) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, false);
xhr.send(null);
}
...@@ -44,13 +44,19 @@ promise_test(function(test) { ...@@ -44,13 +44,19 @@ promise_test(function(test) {
assert_greater_than(entry.startTime, 0); assert_greater_than(entry.startTime, 0);
assert_greater_than(entry.responseEnd, entry.startTime); assert_greater_than(entry.responseEnd, entry.startTime);
} }
return new Promise(function(resolve) { return Promise.race([
new Promise(function(resolve) {
performance.onresourcetimingbufferfull = _ => { performance.onresourcetimingbufferfull = _ => {
resolve('bufferfull'); resolve('bufferfull');
} }
performance.setResourceTimingBufferSize(expectedResources.length); performance.setResourceTimingBufferSize(expectedResources.length);
fetch('dummy.txt'); }),
});
// Race the bufferfull event against another fetch. We should get the
// event before this completes. This allows us to detect a failure
// to dispatch the event without timing out the entire test.
fetch('dummy.txt').then(resp => resp.text())
]);
}) })
.then(function(result) { .then(function(result) {
assert_equals(result, 'bufferfull'); assert_equals(result, 'bufferfull');
......
<script>
if (window.testRunner)
testRunner.dumpAsText();
performance.onresourcetimingbufferfull = function() {
document.body.innerHTML = "PASS";
};
performance.setResourceTimingBufferSize(1);
</script>
<div style='border-image-source: url(#1); background-image: url(#2);'>
<script>
if (window.testRunner)
testRunner.dumpAsText();
performance.onresourcetimingbufferfull = function() {
document.body.appendChild(document.createTextNode("PASS"));
};
performance.setResourceTimingBufferSize(1);
</script>
<iframe src="resources/content-iframe.html"></iframe>
PASS successfullyParsed is true
TEST COMPLETE
PASS. No crash when stop loading on resource timing buffer full.
<html>
<body>
<script src="/js-test-resources/js-test.js"></script>
<script>
if (window.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
}
performance.addEventListener('resourcetimingbufferfull', function(event) {
document.body.innerHTML = "PASS. No crash when stop loading on resource timing buffer full.";
setTimeout("testRunner.notifyDone()", 0);
});
performance.setResourceTimingBufferSize(1);
</script>
</body>
</html>
<html>
<head>
<link rel="help" href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ResourceTiming/Overview.html#extensions-performance-interface">
<script src="/js-test-resources/js-test.js"></script>
<script>
description("This test checks that Performance inherits EventTarget and that addEventListener() works for resourcetimingbufferfull events.");
window.jsTestIsAsync = true;
var bufferFullCount = 0;
var parameter;
function onBufferFull(event) {
shouldBeNull('performance.onresourcetimingbufferfull');
parameter = event;
shouldBe('parameter.__proto__', 'Event.prototype');
bufferFullCount++;
}
shouldBe('Performance.prototype.__proto__', 'EventTarget.prototype');
performance.addEventListener('resourcetimingbufferfull', onBufferFull);
shouldBeNull('performance.onresourcetimingbufferfull');
performance.setResourceTimingBufferSize(2);
</script>
</head>
<body>
<script>
function test() {
// Make sure the onBufferFull callback was called exactly 1 time.
shouldBe('bufferFullCount', '1');
performance.removeEventListener('resourcetimingbufferfull', onBufferFull);
finishJSTest();
}
window.onload = test;
</script>
<script src="resources/empty-script.js"></script>
</body>
</html>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// Scripts appended in JS to ensure setResourceTimingBufferSize is called before. // Scripts appended in JS to ensure setResourceTimingBufferSize is called before.
let counter = performance.getEntriesByType("resource").length; let counter = performance.getEntriesByType("resource").length;
const documentFragment = document.createDocumentFragment(); const documentFragment = document.createDocumentFragment();
while (counter <= default_buffer_size) { while (counter < default_buffer_size) {
const src = "../loading/resources/empty.js?" + counter; const src = "../loading/resources/empty.js?" + counter;
const script = document.createElement('script'); const script = document.createElement('script');
script.type = 'text/javascript'; script.type = 'text/javascript';
......
...@@ -55,7 +55,6 @@ promise_test(function(test) { ...@@ -55,7 +55,6 @@ promise_test(function(test) {
return new Promise(function(resolve) { return new Promise(function(resolve) {
performance.onresourcetimingbufferfull = resolve; performance.onresourcetimingbufferfull = resolve;
performance.setResourceTimingBufferSize(expectedResources.length); performance.setResourceTimingBufferSize(expectedResources.length);
fetch('../../resources/dummy.txt');
}); });
}) })
.then(function() { .then(function() {
......
...@@ -177,19 +177,15 @@ constexpr size_t kDefaultEventTimingBufferSize = 150; ...@@ -177,19 +177,15 @@ constexpr size_t kDefaultEventTimingBufferSize = 150;
Performance::Performance( Performance::Performance(
TimeTicks time_origin, TimeTicks time_origin,
scoped_refptr<base::SingleThreadTaskRunner> task_runner) scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: resource_timing_buffer_size_limit_(kDefaultResourceTimingBufferSize), : resource_timing_buffer_size_(kDefaultResourceTimingBufferSize),
event_timing_buffer_max_size_(kDefaultEventTimingBufferSize), event_timing_buffer_max_size_(kDefaultEventTimingBufferSize),
user_timing_(nullptr), user_timing_(nullptr),
time_origin_(time_origin), time_origin_(time_origin),
observer_filter_options_(PerformanceEntry::kInvalid), observer_filter_options_(PerformanceEntry::kInvalid),
task_runner_(std::move(task_runner)), deliver_observations_timer_(std::move(task_runner),
deliver_observations_timer_(task_runner_,
this, this,
&Performance::DeliverObservationsTimerFired), &Performance::DeliverObservationsTimerFired) {
resource_timing_buffer_full_timer_( }
task_runner_,
this,
&Performance::FireResourceTimingBufferFull) {}
Performance::~Performance() = default; Performance::~Performance() = default;
...@@ -383,7 +379,9 @@ void Performance::clearResourceTimings() { ...@@ -383,7 +379,9 @@ void Performance::clearResourceTimings() {
} }
void Performance::setResourceTimingBufferSize(unsigned size) { void Performance::setResourceTimingBufferSize(unsigned size) {
resource_timing_buffer_size_limit_ = size; resource_timing_buffer_size_ = size;
if (IsResourceTimingBufferFull())
DispatchEvent(*Event::Create(event_type_names::kResourcetimingbufferfull));
} }
bool Performance::PassesTimingAllowCheck( bool Performance::PassesTimingAllowCheck(
...@@ -456,6 +454,10 @@ bool Performance::AllowsTimingRedirect( ...@@ -456,6 +454,10 @@ bool Performance::AllowsTimingRedirect(
void Performance::GenerateAndAddResourceTiming( void Performance::GenerateAndAddResourceTiming(
const ResourceTimingInfo& info, const ResourceTimingInfo& info,
const AtomicString& initiator_type) { const AtomicString& initiator_type) {
if (IsResourceTimingBufferFull() &&
!HasObserverFor(PerformanceEntry::kResource))
return;
ExecutionContext* context = GetExecutionContext(); ExecutionContext* context = GetExecutionContext();
const SecurityOrigin* security_origin = GetSecurityOrigin(context); const SecurityOrigin* security_origin = GetSecurityOrigin(context);
if (!security_origin) if (!security_origin)
...@@ -533,20 +535,15 @@ WebResourceTimingInfo Performance::GenerateResourceTiming( ...@@ -533,20 +535,15 @@ WebResourceTimingInfo Performance::GenerateResourceTiming(
void Performance::AddResourceTiming(const WebResourceTimingInfo& info, void Performance::AddResourceTiming(const WebResourceTimingInfo& info,
const AtomicString& initiator_type) { const AtomicString& initiator_type) {
if (IsResourceTimingBufferFull() &&
!HasObserverFor(PerformanceEntry::kResource))
return;
PerformanceEntry* entry = PerformanceEntry* entry =
PerformanceResourceTiming::Create(info, time_origin_, initiator_type); PerformanceResourceTiming::Create(info, time_origin_, initiator_type);
NotifyObserversOfEntry(*entry); NotifyObserversOfEntry(*entry);
// https://w3c.github.io/resource-timing/#dfn-add-a-performanceresourcetiming-entry if (!IsResourceTimingBufferFull())
if (CanAddResourceTimingEntry() && AddResourceTimingBuffer(*entry);
!resource_timing_buffer_full_event_pending_) {
resource_timing_buffer_.push_back(entry);
return;
}
if (!resource_timing_buffer_full_event_pending_) {
resource_timing_buffer_full_event_pending_ = true;
resource_timing_buffer_full_timer_.StartOneShot(TimeDelta(), FROM_HERE);
}
resource_timing_secondary_buffer_.push_back(entry);
} }
// Called after loadEventEnd happens. // Called after loadEventEnd happens.
...@@ -561,35 +558,6 @@ bool Performance::IsEventTimingBufferFull() const { ...@@ -561,35 +558,6 @@ bool Performance::IsEventTimingBufferFull() const {
return event_timing_buffer_.size() >= event_timing_buffer_max_size_; return event_timing_buffer_.size() >= event_timing_buffer_max_size_;
} }
void Performance::CopySecondaryBuffer() {
// https://w3c.github.io/resource-timing/#dfn-copy-secondary-buffer
while (resource_timing_secondary_buffer_.size() &&
CanAddResourceTimingEntry()) {
PerformanceEntry* entry = resource_timing_secondary_buffer_.front();
DCHECK(entry);
resource_timing_secondary_buffer_.pop_front();
resource_timing_buffer_.push_back(entry);
}
}
void Performance::FireResourceTimingBufferFull(TimerBase*) {
// https://w3c.github.io/resource-timing/#dfn-fire-a-buffer-full-event
while (resource_timing_secondary_buffer_.size()) {
int excess_entries_before = resource_timing_secondary_buffer_.size();
if (!CanAddResourceTimingEntry()) {
DispatchEvent(
*Event::Create(event_type_names::kResourcetimingbufferfull));
}
CopySecondaryBuffer();
int excess_entries_after = resource_timing_secondary_buffer_.size();
if (excess_entries_after >= excess_entries_before) {
resource_timing_secondary_buffer_.clear();
break;
}
}
resource_timing_buffer_full_event_pending_ = false;
}
void Performance::AddEventTimingBuffer(PerformanceEventTiming& entry) { void Performance::AddEventTimingBuffer(PerformanceEventTiming& entry) {
event_timing_buffer_.push_back(&entry); event_timing_buffer_.push_back(&entry);
...@@ -605,7 +573,6 @@ void Performance::clearEventTimings() { ...@@ -605,7 +573,6 @@ void Performance::clearEventTimings() {
event_timing_buffer_.clear(); event_timing_buffer_.clear();
} }
// TODO(yoav): EventTiming should follow a simpler buffering model.
void Performance::setEventTimingBufferMaxSize(unsigned size) { void Performance::setEventTimingBufferMaxSize(unsigned size) {
event_timing_buffer_max_size_ = size; event_timing_buffer_max_size_ = size;
if (IsEventTimingBufferFull()) if (IsEventTimingBufferFull())
...@@ -633,9 +600,15 @@ void Performance::AddPaintTiming(PerformancePaintTiming::PaintType type, ...@@ -633,9 +600,15 @@ void Performance::AddPaintTiming(PerformancePaintTiming::PaintType type,
NotifyObserversOfEntry(*entry); NotifyObserversOfEntry(*entry);
} }
bool Performance::CanAddResourceTimingEntry() { void Performance::AddResourceTimingBuffer(PerformanceEntry& entry) {
// https://w3c.github.io/resource-timing/#dfn-can-add-resource-timing-entry resource_timing_buffer_.push_back(&entry);
return resource_timing_buffer_.size() < resource_timing_buffer_size_limit_;
if (IsResourceTimingBufferFull())
DispatchEvent(*Event::Create(event_type_names::kResourcetimingbufferfull));
}
bool Performance::IsResourceTimingBufferFull() {
return resource_timing_buffer_.size() >= resource_timing_buffer_size_;
} }
void Performance::AddLongTaskTiming( void Performance::AddLongTaskTiming(
...@@ -988,7 +961,6 @@ void Performance::BuildJSONValue(V8ObjectBuilder& builder) const { ...@@ -988,7 +961,6 @@ void Performance::BuildJSONValue(V8ObjectBuilder& builder) const {
void Performance::Trace(blink::Visitor* visitor) { void Performance::Trace(blink::Visitor* visitor) {
visitor->Trace(resource_timing_buffer_); visitor->Trace(resource_timing_buffer_);
visitor->Trace(resource_timing_secondary_buffer_);
visitor->Trace(event_timing_buffer_); visitor->Trace(event_timing_buffer_);
visitor->Trace(navigation_timing_); visitor->Trace(navigation_timing_);
visitor->Trace(user_timing_); visitor->Trace(user_timing_);
......
...@@ -73,7 +73,6 @@ class PerformanceEventTiming; ...@@ -73,7 +73,6 @@ class PerformanceEventTiming;
class StringOrDoubleOrPerformanceMeasureOptions; class StringOrDoubleOrPerformanceMeasureOptions;
using PerformanceEntryVector = HeapVector<Member<PerformanceEntry>>; using PerformanceEntryVector = HeapVector<Member<PerformanceEntry>>;
using PerformanceEntryDeque = HeapDeque<Member<PerformanceEntry>>;
class CORE_EXPORT Performance : public EventTargetWithInlineData { class CORE_EXPORT Performance : public EventTargetWithInlineData {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
...@@ -270,8 +269,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -270,8 +269,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
const ScriptValue& detail, const ScriptValue& detail,
ExceptionState&); ExceptionState&);
void CopySecondaryBuffer();
protected: protected:
Performance(TimeTicks time_origin, Performance(TimeTicks time_origin,
scoped_refptr<base::SingleThreadTaskRunner>); scoped_refptr<base::SingleThreadTaskRunner>);
...@@ -282,8 +279,8 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -282,8 +279,8 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
return nullptr; return nullptr;
} }
bool CanAddResourceTimingEntry(); bool IsResourceTimingBufferFull();
void FireResourceTimingBufferFull(TimerBase*); void AddResourceTimingBuffer(PerformanceEntry&);
void NotifyObserversOfEntry(PerformanceEntry&) const; void NotifyObserversOfEntry(PerformanceEntry&) const;
void NotifyObserversOfEntries(PerformanceEntryVector&); void NotifyObserversOfEntries(PerformanceEntryVector&);
...@@ -293,13 +290,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -293,13 +290,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
virtual void BuildJSONValue(V8ObjectBuilder&) const; virtual void BuildJSONValue(V8ObjectBuilder&) const;
PerformanceEntryVector resource_timing_buffer_; PerformanceEntryVector resource_timing_buffer_;
// The secondary RT buffer, used to store incoming entries after the main unsigned resource_timing_buffer_size_;
// buffer is full, until the resourcetimingbufferfull event fires.
PerformanceEntryDeque resource_timing_secondary_buffer_;
unsigned resource_timing_buffer_size_limit_;
// A flag indicating that the buffer became full, the appropriate event was
// queued, but haven't yet fired.
bool resource_timing_buffer_full_event_pending_ = false;
PerformanceEntryVector event_timing_buffer_; PerformanceEntryVector event_timing_buffer_;
unsigned event_timing_buffer_max_size_; unsigned event_timing_buffer_max_size_;
Member<PerformanceEntry> navigation_timing_; Member<PerformanceEntry> navigation_timing_;
...@@ -314,9 +305,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -314,9 +305,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
HeapLinkedHashSet<TraceWrapperMember<PerformanceObserver>> observers_; HeapLinkedHashSet<TraceWrapperMember<PerformanceObserver>> observers_;
HeapLinkedHashSet<Member<PerformanceObserver>> active_observers_; HeapLinkedHashSet<Member<PerformanceObserver>> active_observers_;
HeapLinkedHashSet<Member<PerformanceObserver>> suspended_observers_; HeapLinkedHashSet<Member<PerformanceObserver>> suspended_observers_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
TaskRunnerTimer<Performance> deliver_observations_timer_; TaskRunnerTimer<Performance> deliver_observations_timer_;
TaskRunnerTimer<Performance> resource_timing_buffer_full_timer_;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment