Commit ec83d167 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

Update performance.measureMemory to the latest proposal

This changes the result format of the API to the latest version of
the proposal at https://github.com/ulan/performance-measure-memory.
Specifically, the result format changes from JS only and per-frame:
{
  total: {
    jsMemoryEstimate: 200*MB,
    jsMemoryRange: [100*MB, 300*MB]
  },
  current: {..},
  other: [..]
}

to more a generic format with breakdown:
{
  bytes: 70*MB,
  breakdown: [
    {bytes: 40*MB, globals: 2, type: 'js', origins: ['foo.com']},
    {bytes: 30*MB, globals: 1, type: 'js', origins: ['bar.com']}
  ]
}

Additionally this patch skips extension contexts and relaxes
cross-origin memory measurement for site-isolated pages.

Bug: 1049093
Change-Id: I997bfe9f6008eaedd0ce5010839232ef3540cad0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2047028
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#740671}
parent 261c5c36
...@@ -613,8 +613,7 @@ static_idl_files_in_core = get_path_info( ...@@ -613,8 +613,7 @@ static_idl_files_in_core = get_path_info(
"//third_party/blink/renderer/core/timing/largest_contentful_paint.idl", "//third_party/blink/renderer/core/timing/largest_contentful_paint.idl",
"//third_party/blink/renderer/core/timing/layout_shift.idl", "//third_party/blink/renderer/core/timing/layout_shift.idl",
"//third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl", "//third_party/blink/renderer/core/timing/measure_memory/measure_memory.idl",
"//third_party/blink/renderer/core/timing/measure_memory/measure_memory_entry.idl", "//third_party/blink/renderer/core/timing/measure_memory/measure_memory_breakdown.idl",
"//third_party/blink/renderer/core/timing/measure_memory/measure_memory_options.idl",
"//third_party/blink/renderer/core/timing/memory_info.idl", "//third_party/blink/renderer/core/timing/memory_info.idl",
"//third_party/blink/renderer/core/timing/performance.idl", "//third_party/blink/renderer/core/timing/performance.idl",
"//third_party/blink/renderer/core/timing/performance_element_timing.idl", "//third_party/blink/renderer/core/timing/performance_element_timing.idl",
......
...@@ -711,8 +711,7 @@ core_dictionary_idl_files = ...@@ -711,8 +711,7 @@ core_dictionary_idl_files =
"resize_observer/resize_observer_options.idl", "resize_observer/resize_observer_options.idl",
"streams/queuing_strategy_init.idl", "streams/queuing_strategy_init.idl",
"timing/measure_memory/measure_memory.idl", "timing/measure_memory/measure_memory.idl",
"timing/measure_memory/measure_memory_entry.idl", "timing/measure_memory/measure_memory_breakdown.idl",
"timing/measure_memory/measure_memory_options.idl",
"timing/performance_mark_options.idl", "timing/performance_mark_options.idl",
"timing/performance_measure_options.idl", "timing/performance_measure_options.idl",
"timing/performance_observer_init.idl", "timing/performance_observer_init.idl",
......
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// https://github.com/ulan/javascript-agent-memory/blob/master/explainer.md // https://github.com/ulan/performance-measure-memory
// The result of performance.measureMemory(). // The result of performance.measureMemory().
dictionary MeasureMemory { dictionary MeasureMemory {
required MeasureMemoryEntry total; required unsigned long long bytes;
MeasureMemoryEntry current; required sequence<MeasureMemoryBreakdown> breakdown;
sequence<MeasureMemoryEntry> other;
}; };
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// https://github.com/ulan/javascript-agent-memory/blob/master/explainer.md // https://github.com/ulan/performance-measure-memory.
// A single entry of performance.measureMemory() result. // A single entry of performance.measureMemory() result.
dictionary MeasureMemoryEntry { dictionary MeasureMemoryBreakdown {
unsigned long long jsMemoryEstimate; unsigned long long bytes;
sequence<unsigned long long> jsMemoryRange; unsigned long long globals;
DOMString url; sequence<DOMString> origins;
DOMString type;
}; };
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
#include "third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.h" #include "third_party/blink/renderer/core/timing/measure_memory/measure_memory_delegate.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory.h" #include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory_entry.h" #include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory_breakdown.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory_options.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h"
...@@ -17,12 +17,10 @@ namespace blink { ...@@ -17,12 +17,10 @@ namespace blink {
MeasureMemoryDelegate::MeasureMemoryDelegate( MeasureMemoryDelegate::MeasureMemoryDelegate(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::Context> context, v8::Local<v8::Context> context,
v8::Local<v8::Promise::Resolver> promise_resolver, v8::Local<v8::Promise::Resolver> promise_resolver)
v8::MeasureMemoryMode mode)
: isolate_(isolate), : isolate_(isolate),
context_(isolate, context), context_(isolate, context),
promise_resolver_(isolate, promise_resolver), promise_resolver_(isolate, promise_resolver) {
mode_(mode) {
context_.SetPhantom(); context_.SetPhantom();
// TODO(ulan): Currently we keep a strong reference to the promise resolver. // TODO(ulan): Currently we keep a strong reference to the promise resolver.
// This may prolong the lifetime of the context by one more GC in the worst // This may prolong the lifetime of the context by one more GC in the worst
...@@ -52,6 +50,10 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) { ...@@ -52,6 +50,10 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) {
// Context do not belong to the same JavaScript agent. // Context do not belong to the same JavaScript agent.
return false; return false;
} }
if (ScriptState::From(context)->World().IsIsolatedWorld()) {
// Context belongs to an extension. Skip it.
return false;
}
const SecurityOrigin* original_security_origin = const SecurityOrigin* original_security_origin =
original_execution_context->GetSecurityContext().GetSecurityOrigin(); original_execution_context->GetSecurityContext().GetSecurityOrigin();
const SecurityOrigin* security_origin = const SecurityOrigin* security_origin =
...@@ -59,7 +61,9 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) { ...@@ -59,7 +61,9 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) {
if (!original_security_origin->IsSameOriginWith(security_origin)) { if (!original_security_origin->IsSameOriginWith(security_origin)) {
// TODO(ulan): Check for COOP/COEP and allow cross-origin contexts that // TODO(ulan): Check for COOP/COEP and allow cross-origin contexts that
// opted in for memory measurement. // opted in for memory measurement.
return false; // Until then we allow cross-origin measurement only for site-isolated
// web pages.
return Platform::Current()->IsLockedToSite();
} }
return true; return true;
} }
...@@ -67,34 +71,52 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) { ...@@ -67,34 +71,52 @@ bool MeasureMemoryDelegate::ShouldMeasure(v8::Local<v8::Context> context) {
namespace { namespace {
// Helper functions for constructing a memory measurement result. // Helper functions for constructing a memory measurement result.
String GetUrl(v8::Local<v8::Context> context) { String GetOrigin(v8::Local<v8::Context> context) {
ExecutionContext* execution_context = ExecutionContext::From(context); ExecutionContext* execution_context = ExecutionContext::From(context);
if (!execution_context) { if (!execution_context) {
// TODO(ulan): Store URL in v8::Context, so that it is available // TODO(ulan): Store URL in v8::Context, so that it is available
// event for detached contexts. // event for detached contexts.
return String("detached"); return String("detached");
} }
return execution_context->Url().GetString(); const SecurityOrigin* security_origin =
execution_context->GetSecurityContext().GetSecurityOrigin();
return security_origin->ToString();
} }
MeasureMemoryEntry* CreateMeasureMemoryEntry(size_t estimate, MeasureMemoryBreakdown* CreateMeasureMemoryBreakdown(size_t bytes,
size_t unattributed) { size_t globals,
MeasureMemoryEntry* result = MeasureMemoryEntry::Create(); const String& type,
result->setJsMemoryEstimate(estimate); const String& origin) {
Vector<uint64_t> range; MeasureMemoryBreakdown* result = MeasureMemoryBreakdown::Create();
range.push_back(estimate); result->setBytes(bytes);
range.push_back(estimate + unattributed); result->setGlobals(globals);
result->setJsMemoryRange(range); result->setType(type);
result->setOrigins(Vector<String>{origin});
return result; return result;
} }
MeasureMemoryEntry* CreateMeasureMemoryEntry(size_t estimate, struct BytesAndGlobals {
size_t unattributed, size_t bytes;
const String& url) { size_t globals;
MeasureMemoryEntry* result = CreateMeasureMemoryEntry(estimate, unattributed); };
result->setUrl(url);
return result; HashMap<String, BytesAndGlobals> GroupByOrigin(
const std::vector<std::pair<v8::Local<v8::Context>, size_t>>&
context_sizes) {
HashMap<String, BytesAndGlobals> per_origin;
for (const auto& context_size : context_sizes) {
const String origin = GetOrigin(context_size.first);
auto it = per_origin.find(origin);
if (it == per_origin.end()) {
per_origin.insert(origin, BytesAndGlobals{context_size.second, 1});
} else {
it->value.bytes += context_size.second;
++it->value.globals;
}
}
return per_origin;
} }
} // anonymous namespace } // anonymous namespace
// Constructs a memory measurement result based on the given list of (context, // Constructs a memory measurement result based on the given list of (context,
...@@ -114,29 +136,20 @@ void MeasureMemoryDelegate::MeasurementComplete( ...@@ -114,29 +136,20 @@ void MeasureMemoryDelegate::MeasurementComplete(
} }
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
size_t total_size = 0; size_t total_size = 0;
size_t current_size = 0;
for (const auto& context_size : context_sizes) { for (const auto& context_size : context_sizes) {
total_size += context_size.second; total_size += context_size.second;
if (context == context_size.first) {
current_size = context_size.second;
}
} }
MeasureMemory* result = MeasureMemory::Create(); MeasureMemory* result = MeasureMemory::Create();
result->setTotal(CreateMeasureMemoryEntry(total_size, unattributed_size)); result->setBytes(total_size + unattributed_size);
if (mode_ == v8::MeasureMemoryMode::kDetailed) { HeapVector<Member<MeasureMemoryBreakdown>> breakdown;
result->setCurrent(CreateMeasureMemoryEntry(current_size, unattributed_size, HashMap<String, BytesAndGlobals> per_origin(GroupByOrigin(context_sizes));
GetUrl(context))); for (const auto& it : per_origin) {
HeapVector<Member<MeasureMemoryEntry>> other; breakdown.push_back(CreateMeasureMemoryBreakdown(
for (const auto& context_size : context_sizes) { it.value.bytes, it.value.globals, "js", it.key));
if (context_size.first == context) {
// The current context was already reported. Skip it.
continue;
}
other.push_back(CreateMeasureMemoryEntry(
context_size.second, unattributed_size, GetUrl(context_size.first)));
}
result->setOther(other);
} }
breakdown.push_back(CreateMeasureMemoryBreakdown(
unattributed_size, context_sizes.size(), "js", "shared"));
result->setBreakdown(breakdown);
v8::Local<v8::Promise::Resolver> promise_resolver = v8::Local<v8::Promise::Resolver> promise_resolver =
promise_resolver_.NewLocal(isolate_); promise_resolver_.NewLocal(isolate_);
promise_resolver promise_resolver
......
...@@ -17,8 +17,7 @@ class MeasureMemoryDelegate : public v8::MeasureMemoryDelegate { ...@@ -17,8 +17,7 @@ class MeasureMemoryDelegate : public v8::MeasureMemoryDelegate {
public: public:
MeasureMemoryDelegate(v8::Isolate* isolate, MeasureMemoryDelegate(v8::Isolate* isolate,
v8::Local<v8::Context> context, v8::Local<v8::Context> context,
v8::Local<v8::Promise::Resolver> promise_resolver, v8::Local<v8::Promise::Resolver> promise_resolver);
v8::MeasureMemoryMode mode);
// v8::MeasureMemoryDelegate overrides. // v8::MeasureMemoryDelegate overrides.
bool ShouldMeasure(v8::Local<v8::Context> context) override; bool ShouldMeasure(v8::Local<v8::Context> context) override;
...@@ -31,7 +30,6 @@ class MeasureMemoryDelegate : public v8::MeasureMemoryDelegate { ...@@ -31,7 +30,6 @@ class MeasureMemoryDelegate : public v8::MeasureMemoryDelegate {
v8::Isolate* isolate_; v8::Isolate* isolate_;
ScopedPersistent<v8::Context> context_; ScopedPersistent<v8::Context> context_;
ScopedPersistent<v8::Promise::Resolver> promise_resolver_; ScopedPersistent<v8::Promise::Resolver> promise_resolver_;
v8::MeasureMemoryMode mode_;
}; };
} // namespace blink } // namespace blink
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// https://github.com/ulan/javascript-agent-memory/blob/master/explainer.md
// Options for performance.measureMemory().
dictionary MeasureMemoryOptions {
boolean detailed;
};
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_performance_measure_options.h" #include "third_party/blink/renderer/bindings/core/v8/string_or_performance_measure_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_measure_memory_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h" #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_mark_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_performance_mark_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_measure_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_performance_measure_options.h"
...@@ -149,7 +148,6 @@ MemoryInfo* Performance::memory() const { ...@@ -149,7 +148,6 @@ MemoryInfo* Performance::memory() const {
ScriptPromise Performance::measureMemory( ScriptPromise Performance::measureMemory(
ScriptState* script_state, ScriptState* script_state,
MeasureMemoryOptions* options,
ExceptionState& exception_state) const { ExceptionState& exception_state) const {
if (!Platform::Current()->IsLockedToSite()) { if (!Platform::Current()->IsLockedToSite()) {
// TODO(ulan): We should check for COOP and COEP here when they ship. // TODO(ulan): We should check for COOP and COEP here when they ship.
...@@ -167,11 +165,6 @@ ScriptPromise Performance::measureMemory( ...@@ -167,11 +165,6 @@ ScriptPromise Performance::measureMemory(
exception_state.RethrowV8Exception(try_catch.Exception()); exception_state.RethrowV8Exception(try_catch.Exception());
return ScriptPromise(); return ScriptPromise();
} }
v8::MeasureMemoryMode mode =
options && options->hasDetailed() && options->detailed()
? v8::MeasureMemoryMode::kDetailed
: v8::MeasureMemoryMode::kSummary;
v8::MeasureMemoryExecution execution = v8::MeasureMemoryExecution execution =
RuntimeEnabledFeatures::ForceEagerMeasureMemoryEnabled( RuntimeEnabledFeatures::ForceEagerMeasureMemoryEnabled(
ExecutionContext::From(script_state)) ExecutionContext::From(script_state))
...@@ -179,7 +172,7 @@ ScriptPromise Performance::measureMemory( ...@@ -179,7 +172,7 @@ ScriptPromise Performance::measureMemory(
: v8::MeasureMemoryExecution::kDefault; : v8::MeasureMemoryExecution::kDefault;
isolate->MeasureMemory(std::make_unique<MeasureMemoryDelegate>( isolate->MeasureMemory(std::make_unique<MeasureMemoryDelegate>(
isolate, context, promise_resolver, mode), isolate, context, promise_resolver),
execution); execution);
return ScriptPromise(script_state, promise_resolver->GetPromise()); return ScriptPromise(script_state, promise_resolver->GetPromise());
} }
......
...@@ -61,7 +61,6 @@ class PerformanceMarkOptions; ...@@ -61,7 +61,6 @@ class PerformanceMarkOptions;
class ExceptionState; class ExceptionState;
class LargestContentfulPaint; class LargestContentfulPaint;
class LayoutShift; class LayoutShift;
class MeasureMemoryOptions;
class MemoryInfo; class MemoryInfo;
class PerformanceElementTiming; class PerformanceElementTiming;
class PerformanceEventTiming; class PerformanceEventTiming;
...@@ -97,7 +96,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData { ...@@ -97,7 +96,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
virtual PerformanceNavigation* navigation() const; virtual PerformanceNavigation* navigation() const;
virtual MemoryInfo* memory() const; virtual MemoryInfo* memory() const;
virtual ScriptPromise measureMemory(ScriptState*, virtual ScriptPromise measureMemory(ScriptState*,
MeasureMemoryOptions*,
ExceptionState& exception_state) const; ExceptionState& exception_state) const;
// Reduce the resolution to prevent timing attacks. See: // Reduce the resolution to prevent timing attacks. See:
......
...@@ -71,7 +71,7 @@ interface Performance : EventTarget { ...@@ -71,7 +71,7 @@ interface Performance : EventTarget {
// https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ // https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
[Exposed=Window, Measure] readonly attribute MemoryInfo memory; [Exposed=Window, Measure] readonly attribute MemoryInfo memory;
[MeasureAs=MeasureMemory, Exposed=(Window,Worker), CallWith=ScriptState, RuntimeEnabled=MeasureMemory, RaisesException] Promise<MeasureMemory> measureMemory(optional MeasureMemoryOptions options = {}); [MeasureAs=MeasureMemory, Exposed=(Window,Worker), CallWith=ScriptState, RuntimeEnabled=MeasureMemory, RaisesException] Promise<MeasureMemory> measureMemory();
// JS Self-Profiling API // JS Self-Profiling API
// https://github.com/WICG/js-self-profiling/ // https://github.com/WICG/js-self-profiling/
......
...@@ -6173,6 +6173,8 @@ http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Skip ] ...@@ -6173,6 +6173,8 @@ http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js [ Skip ]
# Memory measurement tests are run as virtual tests. # Memory measurement tests are run as virtual tests.
external/wpt/measure-memory/measure-memory.tentative.any.html [ Skip ] external/wpt/measure-memory/measure-memory.tentative.any.html [ Skip ]
external/wpt/measure-memory/measure-memory.tentative.any.worker.html [ Skip ] external/wpt/measure-memory/measure-memory.tentative.any.worker.html [ Skip ]
external/wpt/measure-memory/measure-memory-cross-origin-iframe.tentative.window.html [ Skip ]
external/wpt/measure-memory/measure-memory-same-origin-iframe.tentative.window.html [ Skip ]
# Assertion errors need to be fixed # Assertion errors need to be fixed
crbug.com/1034492 http/tests/devtools/unit/filtered-item-selection-dialog-filtering.js [ Pass Failure ] crbug.com/1034492 http/tests/devtools/unit/filtered-item-selection-dialog-filtering.js [ Pass Failure ]
......
...@@ -4,6 +4,5 @@ Tests in this directory are for the proposed performance.measureMemory API. ...@@ -4,6 +4,5 @@ Tests in this directory are for the proposed performance.measureMemory API.
This is not yet standardised and browsers should not be expected to pass This is not yet standardised and browsers should not be expected to pass
these tests. these tests.
See the explainer at See the explainer at https://github.com/ulan/performance-measure-memory
https://github.com/ulan/javascript-agent-memory/blob/master/explainer.md
for more information about the API. for more information about the API.
// META: script=/common/get-host-info.sub.js
// META: script=./resources/common.js
'use strict';
promise_test(async testCase => {
const frame = document.createElement("iframe");
const path = new URL("resources/iframe.sub.html", window.location).pathname;
frame.src = `${CROSS_ORIGIN}${path}`;
document.body.append(frame);
try {
let result = await performance.measureMemory();
checkMeasureMemory(result);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
assert_equals(error.name, 'SecurityError');
}
}, 'Well-formed result of performance.measureMemory with cross-origin iframe.');
// META: script=/common/get-host-info.sub.js
// META: script=./resources/common.js
'use strict';
promise_test(async testCase => {
const frame = document.createElement("iframe");
const path = new URL("resources/iframe.sub.html", window.location).pathname;
frame.src = `${SAME_ORIGIN}${path}`;
document.body.append(frame);
try {
let result = await performance.measureMemory();
checkMeasureMemory(result);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
assert_equals(error.name, 'SecurityError');
}
}, 'Well-formed result of performance.measureMemory with same-origin iframe.');
function checkMeasureMemoryResultEntry(entry, checkUrl) { // META: script=/common/get-host-info.sub.js
assert_own_property(entry, "jsMemoryEstimate"); // META: script=./resources/common.js
assert_own_property(entry, "jsMemoryRange"); 'use strict';
assert_equals(entry.jsMemoryRange.length, 2);
assert_greater_than_equal(entry.jsMemoryRange[1], entry.jsMemoryRange[0]);
assert_greater_than_equal(entry.jsMemoryEstimate, entry.jsMemoryRange[0]);
assert_greater_than_equal(entry.jsMemoryRange[1], entry.jsMemoryEstimate);
if (checkUrl) {
assert_own_property(entry, "url");
}
}
function checkMeasureMemoryResultSummary(result) {
assert_own_property(result, "total");
checkMeasureMemoryResultEntry(result.total, false);
}
function checkMeasureMemoryResultDetails(result) {
assert_own_property(result, "current");
checkMeasureMemoryResultEntry(result.current, true);
assert_own_property(result, "other");
for (other of result.other) {
checkMeasureMemoryResultEntry(other, true);
}
}
promise_test(async testCase => { promise_test(async testCase => {
try { try {
let result = await performance.measureMemory(); let result = await performance.measureMemory();
checkMeasureMemoryResultSummary(result); checkMeasureMemory(result);
} catch (error) { } catch (error) {
if (!(error instanceof DOMException)) { if (!(error instanceof DOMException)) {
throw error; throw error;
} }
assert_equals(error.name, "SecurityError"); assert_equals(error.name, 'SecurityError');
} }
}, 'Well-formed result of performance.measureMemory with default arguments.'); }, 'Well-formed result of performance.measureMemory.');
promise_test(async testcase => {
try {
let result = await performance.measureMemory({detailed: false});
checkMeasureMemoryResultSummary(result);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
assert_equals(error.name, "SecurityError");
}
}, 'well-formed result of performance.measureMemory with detailed=false.');
promise_test(async testcase => {
try {
let result = await performance.measureMemory({detailed: true});
checkMeasureMemoryResultSummary(result);
checkMeasureMemoryResultDetails(result);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
assert_equals(error.name, "SecurityError");
}
}, 'well-formed result of performance.measureMemory with detailed=true.');
const SAME_ORIGIN = {origin: get_host_info().HTTPS_ORIGIN, name: "SAME_ORIGIN"};
const CROSS_ORIGIN = {origin: get_host_info().HTTPS_NOTSAMESITE_ORIGIN, name: "CROSS_ORIGIN"}
function checkMeasureMemoryBreakdown(breakdown) {
assert_own_property(breakdown, 'bytes');
assert_greater_than_equal(breakdown.bytes, 0);
assert_own_property(breakdown, 'globals');
assert_greater_than_equal(breakdown.globals, 0);
assert_own_property(breakdown, 'type');
assert_equals(typeof breakdown.type, 'string');
assert_own_property(breakdown, 'origins');
assert_greater_than_equal(breakdown.origins.length, 1);
for (let origin of breakdown.origins) {
assert_equals(typeof origin, 'string');
}
}
function checkMeasureMemory(result) {
assert_own_property(result, 'bytes');
assert_own_property(result, 'breakdown');
let bytes = 0;
for (let breakdown of result.breakdown) {
checkMeasureMemoryBreakdown(breakdown);
bytes += breakdown.bytes;
}
assert_equals(bytes, result.bytes);
}
\ No newline at end of file
<!doctype html>
<meta charset=utf-8>
<html>
<body>
Hello from iframe.
</body>
</html>
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